- rts8891 backend inclusion

merge-requests/1/head
Stéphane Voltz 2008-03-22 14:33:36 +00:00
rodzic 2330d122e0
commit b85ec879da
17 zmienionych plików z 8704 dodań i 18 usunięć

Wyświetl plik

@ -35,7 +35,7 @@ Backends:
fujitsu: Randolph Bentson, Frederik Ramm, Oliver Schirrmeister (*),
m. allan noah (*)
gphoto2: Peter Fales (*)
genesys: Henning Geinitz (*), Gerhard Jaeger (*), Stephane Voltz (*),
genesys: Henning Geinitz (*), Gerhard Jaeger (*), Stéphane Voltz (*),
Pierre Willenbrock (*)
gt68xx: Sergey Vlasov, Andreas Nowack, David Stevenson, and
Henning Geinitz (*)
@ -52,7 +52,7 @@ Backends:
hs2p: Jeremy Johnson
ibm: M.F., Henning Geinitz (*)
leo: Frank Zago (*)
lexmark: Fred Odendaal (*)
lexmark: Fred Odendaal, Stéphane Voltz (*)
ma1509: Henning Geinitz (*)
matsushita: Frank Zago (*)
microtek: Matthew Marjanovic (*)
@ -77,6 +77,7 @@ Backends:
despeckling filter by Patrick Reynolds,
B&W fixes by Andrew Kuchling
ricoh: Feico W. Dillema
rts8891: Stéphane Voltz (*)
s9036: Ingo Schneider
sceptre: Frank Zago (*)
sharp: Kazuya Fukuda (*) and Abel Deuring (*)

Wyświetl plik

@ -1,3 +1,12 @@
2008-03-02 Stéphane Voltz <stef.dev@free.fr>
* AUTHORS configure configure.in backend/dll.conf.in
backend/Makefile.in backend/rts8891.c backend/rts8891.conf.in
backend/rts8891_devices.c backend/rts8891.h backend/rts8891_low.c
backend/rts8891_low.h backend/rts88xx_lib.c backend/rts88xx_lib.h
doc/descriptions/rts8891.desc doc/descriptions/unsupported.desc
doc/sane-rts8891.man:
rts8891 backend inclusion
2008-03-20 Julien Blache <jb@jblache.org>
* include/Makefile.in: remove _stdint.h and byteorder.h in
distclean target, autogenerated cruft.

Wyświetl plik

@ -181,6 +181,8 @@ DISTFILES = Makefile.in saned.conf.in sane_strstatus.c stubs.c \
pnm.c \
qcam.c qcam.conf.in qcam.h \
ricoh.c ricoh.conf.in ricoh.h ricoh-scsi.c \
rts8891.c rts8891.h rts8891_low.h rts88xx_lib.c \
rts8891_devices.c rts8891_low.c rts88xx_lib.h rts8891.conf.in \
s9036.c s9036.conf.in s9036.h \
sceptre.c sceptre.conf.in sceptre.h \
sharp.c sharp.conf.in sharp.h \
@ -347,6 +349,7 @@ EXTRA_epson = epson_scsi epson_usb
EXTRA_epson2 = epson2_scsi epson_usb epson2_net epson2-io epson2-commands
EXTRA_lexmark = lexmark_low
EXTRA_pixma = pixma_io_sanei pixma_common pixma_mp150 pixma_mp730 pixma_mp750
EXTRA_rts8891 = rts88xx_lib
# When preloading dll, we need to add in all preloaded objects:
libsane-dll.la: $(addsuffix .lo,$(DLL_PRELOAD))
@ -516,6 +519,9 @@ libsane-qcam.la: ../sanei/sanei_constrain_value.lo
libsane-ricoh.la: ../sanei/sanei_config2.lo
libsane-ricoh.la: ../sanei/sanei_constrain_value.lo
libsane-ricoh.la: ../sanei/sanei_scsi.lo
libsane-rts8891.la: $(addsuffix .lo,$(EXTRA_rts8891))
libsane-rts8891.la: ../sanei/sanei_constrain_value.lo
libsane-rts8891.la: ../sanei/sanei_usb.lo
libsane-s9036.la: ../sanei/sanei_config2.lo
libsane-s9036.la: ../sanei/sanei_constrain_value.lo
libsane-s9036.la: ../sanei/sanei_scsi.lo

Wyświetl plik

@ -57,6 +57,7 @@ plustek
#pnm
qcam
ricoh
rts8891
s9036
sceptre
sharp

6029
backend/rts8891.c 100644

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,7 @@
# rts8891.conf: Configuration file for the rts8891 backend
# MODEL
# HP scanjet 4470c
usb 0x03f0 0x0805
# UMAX Astra 4400/4450
usb 0x1606 0x0070

142
backend/rts8891.h 100644
Wyświetl plik

@ -0,0 +1,142 @@
/* sane - Scanner Access Now Easy.
Copyright (C) 2007-2008 stef.dev@free.fr
This file is part of the SANE package.
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 RTS8891_H
#define RTS8891_H
#define ENABLE(OPTION) s->opt[OPTION].cap &= ~SANE_CAP_INACTIVE
#define DISABLE(OPTION) s->opt[OPTION].cap |= SANE_CAP_INACTIVE
#define IS_ACTIVE(OPTION) (((s->opt[OPTION].cap) & SANE_CAP_INACTIVE) == 0)
#define RTS8891_CONFIG_FILE "rts8891.conf"
#ifndef SANE_I18N
#define SANE_I18N(text) text
#endif /* */
#define COLOR_MODE "Color"
#define GRAY_MODE "Gray"
#define LINEART_MODE "Lineart"
/* preferred number of bytes to keep in buffer */
#define PREFERED_BUFFER_SIZE 2097152 /* all scanner memory */
/** List of SANE options
*/
enum Rts8891_Option
{ OPT_NUM_OPTS = 0,
OPT_MODE_GROUP,
OPT_MODE,
OPT_PREVIEW,
OPT_RESOLUTION,
OPT_GEOMETRY_GROUP,
OPT_TL_X, /* top-left x */
OPT_TL_Y, /* top-left y */
OPT_BR_X, /* bottom-right x */
OPT_BR_Y, /* bottom-right y */
/* advanced image enhancement options */
OPT_ENHANCEMENT_GROUP,
OPT_THRESHOLD,
OPT_CUSTOM_GAMMA, /* toggle to enable custom gamma tables */
OPT_GAMMA_VECTOR,
OPT_GAMMA_VECTOR_R,
OPT_GAMMA_VECTOR_G,
OPT_GAMMA_VECTOR_B,
/* advanced options */
OPT_ADVANCED_GROUP,
OPT_LAMP_ON,
OPT_LAMP_OFF,
/* button group */
OPT_BUTTON_GROUP,
OPT_BUTTON_1,
OPT_BUTTON_2,
OPT_BUTTON_3,
OPT_BUTTON_4,
OPT_BUTTON_5,
OPT_BUTTON_6,
OPT_BUTTON_7,
OPT_BUTTON_8,
OPT_BUTTON_9,
OPT_BUTTON_10,
OPT_BUTTON_11,
/* must come last: */
NUM_OPTIONS
};
/** Scanner object. This struct holds informations usefull for
* the functions defined in SANE's standard. Informations closer
* to the hardware are in the Rts8891_Device structure.
*/
typedef struct Rts8891_Scanner
{
/**< Next handle in linked list */
struct Rts8891_Scanner *next;
/**< Low-level device object */
struct Rts8891_Device *dev;
/* SANE data */
/**< We are currently scanning */
SANE_Bool scanning;
/**< Data read is in non blocking mode */
SANE_Bool non_blocking;
/**< Gray scans are emulated */
SANE_Bool emulated_gray;
SANE_Option_Descriptor opt[NUM_OPTIONS];
/**< Option descriptors */
Option_Value val[NUM_OPTIONS]; /**< Option values */
SANE_Parameters params; /**< SANE Parameters */
/**< bytes to send to frontend for the scan */
SANE_Int to_send;
/**< bytes currently sent to frontend during the scan */
SANE_Int sent;
} Rts8891_Scanner;
#endif /* not RTS8891_H */

Wyświetl plik

@ -0,0 +1,177 @@
/* sane - Scanner Access Now Easy.
Copyright (C) 2007-2008 stef.dev@free.fr
This file is part of the SANE package.
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.
*/
/* here we have the various device settings...
*/
static Rts8891_Model hp4470c_model = {
"HP4470c", /* Name */
"Hewlett-Packard", /* Device vendor string */
"4470c", /* Device model name */
"flatbed scanner", /* Device type */
{1200, 600, 300, 150, 75, 0}, /* possible x-resolutions */
{600, 300, 150, 0}, /* possible y-resolutions */
1200, /* max physical x dpi */
600, /* max physical y dpi */
150, /* min physical y dpi */
SANE_FIX (8.3), /* Start of scan area in mm (x) */
SANE_FIX (3.0), /* Start of scan area in mm (y) */
SANE_FIX (215.9), /* Size of scan area in mm (x) */
SANE_FIX (298.1), /* Size of scan area in mm (y) */
SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */
SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */
SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */
SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */
24, 12, 0, /* R, G, and B CCD Line-distance correction in lines at
max motor resolution */
/* default gamma table */
{0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c,
0x30, 0x34, 0x38, 0x3c, 0x40, 0x44, 0x48, 0x4c, 0x50, 0x52, 0x53, 0x55,
0x57, 0x58, 0x5a, 0x5c, 0x5d, 0x5f, 0x60, 0x62, 0x63, 0x64, 0x66, 0x67,
0x68, 0x6a, 0x6b, 0x6c, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x74, 0x75, 0x76,
0x77, 0x78, 0x79, 0x7a, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8d, 0x8e,
0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x97, 0x98, 0x99,
0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3,
0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac,
0xac, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb1, 0xb1, 0xb2, 0xb3, 0xb4, 0xb4,
0xb5, 0xb6, 0xb6, 0xb7, 0xb8, 0xb8, 0xb9, 0xba, 0xba, 0xbb, 0xbc, 0xbc,
0xbd, 0xbe, 0xbe, 0xbf, 0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc3, 0xc3, 0xc4,
0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xcb, 0xcb,
0xcc, 0xcc, 0xcd, 0xce, 0xce, 0xcf, 0xcf, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2,
0xd3, 0xd3, 0xd4, 0xd5, 0xd5, 0xd6, 0xd6, 0xd7, 0xd7, 0xd8, 0xd9, 0xd9,
0xda, 0xda, 0xdb, 0xdb, 0xdc, 0xdc, 0xdd, 0xdd, 0xde, 0xdf, 0xdf, 0xe0,
0xe0, 0xe1, 0xe1, 0xe2, 0xe2, 0xe3, 0xe3, 0xe4, 0xe4, 0xe5, 0xe5, 0xe6,
0xe6, 0xe7, 0xe7, 0xe8, 0xe8, 0xe9, 0xe9, 0xea, 0xea, 0xeb, 0xeb, 0xec,
0xec, 0xed, 0xed, 0xee, 0xee, 0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2,
0xf2, 0xf3, 0xf3, 0xf4, 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8,
0xf8, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfc, 0xfc, 0xfd, 0xfd,
0xfe, 0xfe, 0xff, 0xff},
/* number of buttons */
11,
/* button names */
{"plus", "minus", "copy", "mail", "image-copy", "www", "scan", "power",
"cancel", "options", "toggle-mode"},
/* button titles */
{"plus", "minus", "copy", "mail", "image copy", "www", "scan", "power",
"cancel", "options", "toggle color/gray mode"},
/* flags */
RTS8891_FLAG_EMULATED_GRAY_MODE
};
static Rts8891_Model astra4400_model = {
"Astra 4400", /* Name */
"UMAX", /* Device vendor string */
"Astra 4400", /* Device model name */
"flatbed scanner", /* Device type */
{1200, 600, 300, 150, 75, 0}, /* possible x-resolutions */
{600, 300, 150, 0}, /* possible y-resolutions */
1200, /* max physical x dpi */
600, /* max physical y dpi */
150, /* min physical y dpi */
SANE_FIX (8.3), /* Start of scan area in mm (x) */
SANE_FIX (3.0), /* Start of scan area in mm (y) */
SANE_FIX (215.9), /* Size of scan area in mm (x) */
SANE_FIX (298.1), /* Size of scan area in mm (y) */
SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */
SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */
SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */
SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */
24, 12, 0, /* R, G, and B CCD Line-distance correction in lines at
max motor resolution */
/* default gamma table */
{0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c,
0x30, 0x34, 0x38, 0x3c, 0x40, 0x44, 0x48, 0x4c, 0x50, 0x52, 0x53, 0x55,
0x57, 0x58, 0x5a, 0x5c, 0x5d, 0x5f, 0x60, 0x62, 0x63, 0x64, 0x66, 0x67,
0x68, 0x6a, 0x6b, 0x6c, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x74, 0x75, 0x76,
0x77, 0x78, 0x79, 0x7a, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8d, 0x8e,
0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x97, 0x98, 0x99,
0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3,
0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac,
0xac, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb1, 0xb1, 0xb2, 0xb3, 0xb4, 0xb4,
0xb5, 0xb6, 0xb6, 0xb7, 0xb8, 0xb8, 0xb9, 0xba, 0xba, 0xbb, 0xbc, 0xbc,
0xbd, 0xbe, 0xbe, 0xbf, 0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc3, 0xc3, 0xc4,
0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xcb, 0xcb,
0xcc, 0xcc, 0xcd, 0xce, 0xce, 0xcf, 0xcf, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2,
0xd3, 0xd3, 0xd4, 0xd5, 0xd5, 0xd6, 0xd6, 0xd7, 0xd7, 0xd8, 0xd9, 0xd9,
0xda, 0xda, 0xdb, 0xdb, 0xdc, 0xdc, 0xdd, 0xdd, 0xde, 0xdf, 0xdf, 0xe0,
0xe0, 0xe1, 0xe1, 0xe2, 0xe2, 0xe3, 0xe3, 0xe4, 0xe4, 0xe5, 0xe5, 0xe6,
0xe6, 0xe7, 0xe7, 0xe8, 0xe8, 0xe9, 0xe9, 0xea, 0xea, 0xeb, 0xeb, 0xec,
0xec, 0xed, 0xed, 0xee, 0xee, 0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2,
0xf2, 0xf3, 0xf3, 0xf4, 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8,
0xf8, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfc, 0xfc, 0xfd, 0xfd,
0xfe, 0xfe, 0xff, 0xff},
/* number of buttons */
11,
/* button names */
{"plus", "minus", "copy", "mail", "image-copy", "www", "scan", "power",
"cancel", "options", "toggle-mode"},
/* button titles */
{"plus", "minus", "copy", "mail", "image copy", "www", "scan", "power",
"cancel", "options", "toggle color/gray mode"},
/* flags */
RTS8891_FLAG_EMULATED_GRAY_MODE
};
/* full list of supported devices: vendor, product, description structure */
static Rts8891_USB_Device_Entry rts8891_usb_device_list[] = {
{0x03f0, 0x0805, &hp4470c_model},
{0x1606, 0x0070, &astra4400_model},
{0, 0, NULL}
};

Wyświetl plik

@ -0,0 +1,771 @@
/* sane - Scanner Access Now Easy.
Copyright (C) 2007-2008 stef.dev@free.fr
This file is part of the SANE package.
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.
*/
/* this file contains all the low level functions needed for the higher level
* functions of the sane standard. They are put there to keep files smaller
* and separate functions with different goals.
*/
#include "sane/config.h"
#include "sane/sane.h"
#include "sane/sanei_backend.h"
#include "sane/sanei_usb.h"
#include <stdio.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include "rts8891_low.h"
#define RTS8891_BUILD 2
#define RTS8891_MAX_REGISTERS 244
/* init rts8891 library */
static void
rts8891_low_init (void)
{
DBG_INIT ();
DBG (DBG_info, "RTS8891 low-level functions, version %d.%d-rc-%d\n",
V_MAJOR, V_MINOR, RTS8891_BUILD);
}
/****************************************************************/
/* ASIC specific functions */
/****************************************************************/
/* write all registers, taking care of the special 0xaa value which
* must be escaped with a zero
*/
static SANE_Status
rts8891_write_all (SANE_Int devnum, SANE_Byte * regs, SANE_Int count)
{
SANE_Status status = SANE_STATUS_GOOD;
SANE_Byte local_regs[RTS8891_MAX_REGISTERS];
size_t size = 0;
SANE_Byte buffer[260];
unsigned int i, j;
char message[256 * 5];
if (DBG_LEVEL > DBG_io)
{
for (i = 0; i < (unsigned int) count; i++)
{
if (i != 0xb3)
sprintf (message + 5 * i, "0x%02x ", regs[i]);
else
sprintf (message + 5 * i, "---- ");
}
DBG (DBG_io, "rts8891_write_all : write_all(0x00,%d)=%s\n", count,
message);
}
/* copy register set and escaping 0xaa values */
/* b0, b1 abd b3 values may be scribled, but that isn't important */
/* since they are read-only registers */
j = 0;
for (i = 0; i < 0xb3; i++)
{
local_regs[j] = regs[i];
if (local_regs[j] == 0xaa && i < 0xb3)
{
j++;
local_regs[j] = 0x00;
}
j++;
}
buffer[0] = 0x88;
buffer[1] = 0;
buffer[2] = 0x00;
buffer[3] = 0xb3;
for (i = 0; i < j; i++)
buffer[i + 4] = local_regs[i];
/* the USB block is size + 4 bytes of header long */
size = j + 4;
if (sanei_usb_write_bulk (devnum, buffer, &size) != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"rts88xx_write_all : write registers part 1 failed ...\n");
return SANE_STATUS_IO_ERROR;
}
size = count - 0xb4; /* we need to substract one reg since b3 won't be written */
buffer[0] = 0x88;
buffer[1] = 0xb4;
buffer[2] = 0x00;
buffer[3] = size;
for (i = 0; i < size; i++)
buffer[i + 4] = regs[0xb4 + i];
/* the USB block is size + 4 bytes of header long */
size += 4;
if (sanei_usb_write_bulk (devnum, buffer, &size) != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"rts88xx_write_all : write registers part 2 failed ...\n");
return SANE_STATUS_IO_ERROR;
}
return status;
}
/* this functions "commits" pending scan command */
static SANE_Status
rts8891_commit (SANE_Int devnum, SANE_Byte value)
{
SANE_Status status = SANE_STATUS_GOOD;
SANE_Byte reg;
reg = value;
status = sanei_rts88xx_write_reg (devnum, 0xd3, &reg);
status = sanei_rts88xx_cancel (devnum);
status = sanei_rts88xx_write_control (devnum, 0x08);
status = sanei_rts88xx_write_control (devnum, 0x08);
return status;
}
/* this functions reads button status */
static SANE_Status
rts8891_read_buttons (SANE_Int devnum, SANE_Int * mask)
{
SANE_Status status = SANE_STATUS_GOOD;
SANE_Byte reg;
/* check CONTROL_REG */
sanei_rts88xx_read_reg (devnum, CONTROL_REG, &reg);
/* read 'base' button status */
sanei_rts88xx_read_reg (devnum, 0x25, &reg);
DBG (DBG_io, "rts8891_read_buttons: r25=0x%02x\n", reg);
*mask |= reg;
/* read 'extended' button status */
sanei_rts88xx_read_reg (devnum, 0x1a, &reg);
DBG (DBG_io, "rts8891_read_buttons: r1a=0x%02x\n", reg);
*mask |= reg << 8;
/* clear register r25 */
reg = 0x00;
status = sanei_rts88xx_write_reg (devnum, 0x25, &reg);
/* clear register r1a */
sanei_rts88xx_read_reg (devnum, 0x1a, &reg);
reg = 0x00;
status = sanei_rts88xx_write_reg (devnum, 0x1a, &reg);
DBG (DBG_info, "rts8891_read_buttons: mask=0x%04x\n", *mask);
return status;
}
/*
* Does a simple scan based on the given register set, returning data in a
* preallocated buffer of the claimed size.
* sanei_rts88xx_data_count cannot be made reliable, when the announced data
* amount is read, it may no be ready, leading to errors. To work around
* it, we read data count one more time before reading.
*/
static SANE_Status
rts8891_simple_scan (SANE_Int devnum, SANE_Byte * regs, int regcount,
SANE_Int format, SANE_Word total, unsigned char *image)
{
SANE_Word count, read, len, dummy;
SANE_Status status = SANE_STATUS_GOOD;
SANE_Byte control;
rts8891_write_all (devnum, regs, regcount);
rts8891_commit (devnum, format);
read = 0;
count = 0;
while (count == 0)
{
status = sanei_rts88xx_data_count (devnum, &count);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "simple_scan: failed to wait for data\n");
return status;
}
if (count == 0)
{
status = sanei_rts88xx_read_reg (devnum, CONTROL_REG, &control);
if (((control & 0x08) == 0) || (status != SANE_STATUS_GOOD))
{
DBG (DBG_error, "simple_scan: failed to wait for data\n");
return SANE_STATUS_IO_ERROR;
}
}
}
/* data reading */
read = 0;
while ((read < total) && (count != 0 || (control & 0x08) == 0x08))
{
/* sync ? */
status = sanei_rts88xx_data_count (devnum, &dummy);
/* read */
if (count > 0)
{
len = count;
/* read even size unless last chunk */
if ((len & 1) && (read + len < total))
{
len++;
}
if (len > RTS88XX_MAX_XFER_SIZE)
{
len = RTS88XX_MAX_XFER_SIZE;
}
if (len > 0)
{
status = sanei_rts88xx_read_data (devnum, &len, image + read);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"simple_scan: failed to read from scanner\n");
return status;
}
read += len;
}
}
/* don't try to read data count if we have enough data */
if (read < total)
{
status = sanei_rts88xx_data_count (devnum, &count);
}
else
{
count = 0;
}
if (count == 0)
{
sanei_rts88xx_read_reg (devnum, CONTROL_REG, &control);
}
}
/* sanity check */
if (read < total)
{
DBG (DBG_io2, "simple_scan: ERROR, %d bytes missing ... \n",
total - read);
}
/* wait for the motor to stop */
do
{
sanei_rts88xx_read_reg (devnum, CONTROL_REG, &control);
}
while ((control & 0x08) == 0x08);
return status;
}
/**
* set the data format. Is part of the commit sequence
*/
static SANE_Int
rts8891_data_format (SANE_Int dpi)
{
SANE_Byte reg = 0x00;
switch (dpi)
{
case 75:
reg = 0x02;
break;
case 150:
reg = 0x0e; /* 0x0b : gray */
break;
case 300:
reg = 0x17;
break;
case 600:
reg = 0x02; /* 0x0e : gray */
break;
case 1200:
reg = 0x17; /* 0x05 : gray */
break;
}
return reg;
}
/**
* set up default values for a 75xdpy, 150 ydpi scan
*/
static void
rts8891_set_default_regs (SANE_Byte * scanner_regs)
{
SANE_Byte default_75[RTS8891_MAX_REGISTERS] =
{ 0xe5, 0x41, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x0a, 0x0a, 0x0a, 0x70,
0x00, 0x00, 0x00, 0x00, 0x28, 0x3f, 0xff, 0x20, 0xf8, 0x28, 0x07, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
0x00, 0x3a, 0xf2, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x8c,
0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x14, 0x18, 0x15, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0x3f, 0x80, 0x68, 0x00, 0x00,
0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc,
0x27, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x0e, 0x00, 0x00, 0xf0, 0xff, 0xf5, 0xf7, 0xea, 0x0b, 0x03, 0x05, 0x86,
0x1b, 0x30, 0xf6, 0xa2, 0x27, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
unsigned int i;
for (i = 0; i < RTS8891_MAX_REGISTERS; i++)
scanner_regs[i] = default_75[i];
}
static SANE_Status
rts8891_move (SANE_Int devnum, SANE_Byte * regs, SANE_Int distance,
SANE_Bool forward)
{
SANE_Status status = SANE_STATUS_GOOD;
DBG (DBG_proc, "rts8891_move: start\n");
DBG (DBG_io, "rts8891_move: %d lines %s\n", distance,
forward == SANE_TRUE ? "forward" : "backward");
/* prepare scan */
rts8891_set_default_regs (regs);
regs[0x10] = 0x20;
regs[0x11] = 0x28;
regs[0x32] = 0x80;
regs[0x33] = 0x81;
regs[0x35] = 0x10;
regs[0x36] = 0x24;
regs[0x39] = 0x02;
regs[0x3a] = 0x0e;
regs[0x64] = 0x01;
regs[0x65] = 0x20;
regs[0x79] = 0x20;
regs[0x7a] = 0x01;
regs[0x80] = 0x32;
regs[0x82] = 0x33;
regs[0x85] = 0x46;
regs[0x86] = 0x0b;
regs[0x87] = 0x8c;
regs[0x88] = 0x10;
regs[0x89] = 0xb2;
regs[0x8d] = 0x3b;
regs[0x8e] = 0x60;
regs[0x90] = 0x1c;
regs[0xb2] = 0x16; /* 0x10 : stop when at home, 0x04: no data */
regs[0xc0] = 0x00;
regs[0xc1] = 0x00;
regs[0xc3] = 0x00;
regs[0xc4] = 0x00;
regs[0xc5] = 0x00;
regs[0xc6] = 0x00;
regs[0xc7] = 0x00;
regs[0xc8] = 0x00;
regs[0xca] = 0x00;
regs[0xcd] = 0x00;
regs[0xce] = 0x00;
regs[0xcf] = 0x00;
regs[0xd0] = 0x00;
regs[0xd1] = 0x00;
regs[0xd2] = 0x00;
regs[0xd3] = 0x00;
regs[0xd4] = 0x00;
regs[0xd6] = 0x6b;
regs[0xd7] = 0x00;
regs[0xd8] = 0x00;
regs[0xd9] = 0xad;
regs[0xda] = 0xa7;
regs[0xe2] = 0x17;
regs[0xe3] = 0x0d;
regs[0xe4] = 0x06;
regs[0xe5] = 0xf9;
regs[0xe7] = 0x53;
regs[0xe8] = 0x02;
regs[0xe9] = 0x02;
/* disable CCD */
regs[0] = 0xf5;
sanei_rts88xx_set_status (devnum, regs, 0x20, 0x28);
sanei_rts88xx_set_scan_area (regs, distance, distance + 1, 100, 200);
sanei_rts88xx_set_gain (regs, 16, 16, 16);
sanei_rts88xx_set_offset (regs, 127, 127, 127);
/* forward/backward */
/* 0x2c is forward, 0x24 backward */
if (forward == SANE_TRUE)
{ /* forward */
regs[0x36] = regs[0x36] | 0x08;
}
else
{ /* backward */
regs[0x36] = regs[0x36] & 0xf7;
}
/* write regiters values */
status = rts8891_write_all (devnum, regs, RTS8891_MAX_REGISTERS);
/* commit it */
rts8891_commit (devnum, 0x00);
return status;
}
/**
* move the head backward by a huge line number then poll home sensor until
* head has get back home. We have our own copy of the registers to avoid
* messing scanner status
*/
static SANE_Status
rts8891_park (SANE_Int devnum, SANE_Byte * regs)
{
SANE_Status status = SANE_STATUS_GOOD;
SANE_Byte motor, sensor, reg;
DBG (DBG_proc, "rts8891_park: start\n");
rts8891_move (devnum, regs, 8000, SANE_FALSE);
/* wait for controller home bit to raise, no timeout */
/* at each loop we check that motor is on, then that the sensor bit it cleared */
do
{
sanei_rts88xx_read_reg (devnum, CONTROL_REG, &motor);
sanei_rts88xx_read_reg (devnum, CONTROLER_REG, &sensor);
}
while ((motor & 0x08) && ((sensor & 0x02) == 0));
/* check for error */
if (((motor & 0x08) == 0x00) && ((sensor & 0x02) == 0))
{
DBG (DBG_error,
"rts8891_park: error, motor stopped before head parked\n");
status = SANE_STATUS_INVAL;
}
/* re-enable CCD */
regs[0] = regs[0] & 0xef;
sanei_rts88xx_cancel (devnum);
/* reset ? so we don't need to read data */
reg = 0;
/* b7: movement on/off, b3-b0 : movement divisor */
sanei_rts88xx_write_reg (devnum, 0x33, &reg);
sanei_rts88xx_write_reg (devnum, 0x33, &reg);
/* movement direction */
sanei_rts88xx_write_reg (devnum, 0x36, &reg);
sanei_rts88xx_cancel (devnum);
DBG (DBG_proc, "rts8891_park: end\n");
return status;
}
/* reads data from scanner.
* First we wait for some data to be available and then loop reading
* from scanner until the required amount is reached.
* We handle non blocking I/O by returning immediatly (with SANE_STATUS_BUSY)
* if there is no data available from scanner. But once read is started,
* all the required amount is read. Once wait for data succeeded, we still poll
* for data in order no to read it too fast, but we don' take care of non blocking
* mode since we cope with it on first data wait.
*/
static SANE_Status
read_data (struct Rts8891_Scanner *scanner, SANE_Byte * dest, SANE_Int length)
{
SANE_Status status = SANE_STATUS_GOOD;
SANE_Int count, read, len, dummy;
struct Rts8891_Device *dev = scanner->dev;
static FILE *raw = NULL; /* for debugging purpose we need it static */
SANE_Byte control = 0x08;
unsigned char buffer[RTS88XX_MAX_XFER_SIZE];
DBG (DBG_proc, "read_data: start\n");
DBG (DBG_proc, "read_data: requiring %d bytes\n", length);
/* wait for data being available and handle non blocking mode */
/* only when data reading hasn't produce any data yet */
if (dev->read == 0)
{
do
{
status = sanei_rts88xx_data_count (dev->devnum, &count);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "read_data: failed to wait for data\n");
return status;
}
if (count == 0)
{
sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control);
if ((control & 0x08) == 0 && (count == 0))
{
DBG (DBG_error,
"read_data: scanner stopped being busy before data are available\n");
return SANE_STATUS_IO_ERROR;
}
}
/* in case there is no data, we return BUSY since this mean */
/* that scanning head hasn't reach is position and data hasn't */
/* come yet */
if (scanner->non_blocking && count == 0)
{
dev->regs[LAMP_REG] = 0x8d;
sanei_rts88xx_write_reg (dev->devnum, LAMP_REG,
&(dev->regs[LAMP_REG]));
DBG (DBG_io, "read_data: no data vailable\n");
DBG (DBG_proc, "read_data: end\n");
return SANE_STATUS_DEVICE_BUSY;
}
}
while (count == 0);
}
else
{ /* start of read for a new block */
status = sanei_rts88xx_data_count (dev->devnum, &count);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "read_data: failed to wait for data\n");
return status;
}
if (count == 0)
{
sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control);
if ((control & 0x08) == 0 && (count == 0))
{
DBG (DBG_error,
"read_data: scanner stopped being busy before data are available\n");
return SANE_STATUS_IO_ERROR;
}
}
}
/* fill scanned data buffer */
read = 0;
/* now loop reading data until we have the amount requested */
/* we also take care of not reading too much data */
while (read < length && dev->read < dev->to_read
&& ((control & 0x08) == 0x08))
{
/* used to sync */
if (dev->read == 0)
{
status = sanei_rts88xx_data_count (dev->devnum, &dummy);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "read_data: failed to read data count\n");
return status;
}
}
/* if there is data to read, read it */
if (count > 0)
{
len = count;
if (len > RTS88XX_MAX_XFER_SIZE)
{
len = RTS88XX_MAX_XFER_SIZE;
}
/* we only read even size blocks of data */
if (len & 1)
{
DBG (DBG_io, "read_data: round to next even number\n");
len++;
}
if (len > length - read)
{
len = length - read;
}
status = sanei_rts88xx_read_data (dev->devnum, &len, dest + read);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "read_data: failed to read from scanner\n");
return status;
}
/* raw data tracing */
if (DBG_LEVEL >= DBG_io2)
{
/* open a new file only when no data scanned */
if (dev->read == 0)
{
raw = fopen ("raw_data.pnm", "wb");
if (raw != NULL)
{
/* PNM header */
fprintf (raw, "P%c\n%d %d\n255\n",
scanner->params.format ==
SANE_FRAME_RGB
|| scanner->emulated_gray ==
SANE_TRUE ? '6' : '5', dev->pixels,
dev->lines);
}
}
if (raw != NULL)
{
fwrite (dest + read, 1, len, raw);
}
}
/* move pointer and counter */
read += len;
dev->read += len;
DBG (DBG_io2, "read_data: %d/%d\n", dev->read, dev->to_read);
}
/* in fast scan mode, read data count
* in slow scan, head moves by the amount of data read */
status = sanei_rts88xx_data_count (dev->devnum, &count);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "read_data: failed to read data count\n");
return status;
}
/* if no data, check if still scanning */
if (count == 0 && dev->read < dev->to_read)
{
sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control);
if ((control & 0x08) == 0x00)
{
DBG (DBG_error,
"read_data: scanner stopped being busy before data are available\n");
return SANE_STATUS_IO_ERROR;
}
}
}
/* end of physical reads */
if (dev->read >= dev->to_read)
{
/* check there is no more data in case of a bug */
sanei_rts88xx_data_count (dev->devnum, &count);
if (count > 0)
{
DBG (DBG_warn,
"read_data: %d bytes are still available from scanner\n",
count);
/* flush left-over data */
while (count > 0)
{
len = count;
if (len > RTS88XX_MAX_XFER_SIZE)
{
len = RTS88XX_MAX_XFER_SIZE;
}
/* we only read even size blocks of data */
if (len & 1)
{
len++;
}
sanei_rts88xx_read_data (dev->devnum, &len, buffer);
sanei_rts88xx_data_count (dev->devnum, &count);
}
}
/* wait for motor to stop at the end of the scan */
do
{
sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control);
}
while ((control & 0x08) != 0);
/* close log file if needed */
if (DBG_LEVEL >= DBG_io2)
{
if (raw != NULL)
{
fclose (raw);
raw = NULL;
}
}
}
DBG (DBG_io, "read_data: read %d bytes from scanner\n", length);
DBG (DBG_proc, "read_data: end\n");
return status;
}
/**
* set scanner idle before leaving xxx_quiet()
write_reg(0x33,1)=0x00
write_reg(0x33,1)=0x00
write_reg(0x36,1)=0x00
prepare();
------
write_reg(LAMP_REG,1)=0x80
write_reg(LAMP_REG,1)=0xad
read_reg(0x14,2)=0xf8 0x28
write_reg(0x14,2)=0x78 0x28
get_status()=0x20 0x3f
read_reg(0xb1,1)=0x00
read_control()=0x00
reset_lamp()=(0x20,0x3f)
write_reg(LAMP_REG,1)=0x8d
write_reg(LAMP_REG,1)=0xad
*/

Wyświetl plik

@ -0,0 +1,242 @@
/* sane - Scanner Access Now Easy.
Copyright (C) 2007-2008 stef.dev@free.fr
This file is part of the SANE package.
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 RTS8891_LOW_H
#define RTS8891_LOW_H
#include <stddef.h>
#include "../include/sane/sane.h"
#define DBG_error0 0 /* errors/warnings printed even with devuglevel 0 */
#define DBG_error 1 /* fatal errors */
#define DBG_init 2 /* initialization and scanning time messages */
#define DBG_warn 3 /* warnings and non-fatal errors */
#define DBG_info 4 /* informational messages */
#define DBG_proc 5 /* starting/finishing functions */
#define DBG_io 6 /* io functions */
#define DBG_io2 7 /* io functions that are called very often */
#define DBG_data 8 /* log image data */
#define MM_PER_INCH 25.4
/* Flags */
#define RTS8891_FLAG_UNTESTED (1 << 0) /* Print a warning for these scanners */
#define RTS8891_FLAG_EMULATED_GRAY_MODE (2 << 0) /* gray scans are emulated using comor modes */
#define LOWORD(x) ((u_int16_t)(x & 0xffff))
#define HIWORD(x) ((u_int16_t)(x >> 16))
#define LOBYTE(x) ((u_int8_t)((x) & 0xFF))
#define HIBYTE(x) ((u_int8_t)((x) >> 8))
#define MAX_SCANNERS 32
#define MAX_RESOLUTIONS 16
#define SENSOR_TYPE_BARE 0 /* sensor for hp4470 sold bare */
#define SENSOR_TYPE_XPA 1 /* sensor for hp4470 sold with XPA */
/* Forward typedefs */
typedef struct Rts8891_Device Rts8891_Device;
/*
* defines for RTS8891 registers name
*/
#define BUTTONS_REG2 0x1a
#define LINK_REG 0xb1
#define LAMP_REG 0xd9
#define LAMP_BRIGHT_REG 0xda
/* this struc describes a particular model which is handled by the backend */
/* available resolutions, physical goemetry, scanning area, ... */
typedef struct Rts8891_Model
{
SANE_String_Const name;
SANE_String_Const vendor;
SANE_String_Const product;
SANE_String_Const type;
SANE_Int xdpi_values[MAX_RESOLUTIONS]; /* possible x resolutions */
SANE_Int ydpi_values[MAX_RESOLUTIONS]; /* possible y resolutions */
SANE_Int max_xdpi; /* physical maximum x dpi */
SANE_Int max_ydpi; /* physical maximum y dpi */
SANE_Int min_ydpi; /* physical minimum y dpi */
SANE_Fixed x_offset; /* Start of scan area in mm */
SANE_Fixed y_offset; /* Start of scan area in mm */
SANE_Fixed x_size; /* Size of scan area in mm */
SANE_Fixed y_size; /* Size of scan area in mm */
SANE_Fixed x_offset_ta; /* Start of scan area in TA mode in mm */
SANE_Fixed y_offset_ta; /* Start of scan area in TA mode in mm */
SANE_Fixed x_size_ta; /* Size of scan area in TA mode in mm */
SANE_Fixed y_size_ta; /* Size of scan area in TA mode in mm */
/* Line-distance correction (in pixel at max optical dpi) for CCD scanners */
SANE_Int ld_shift_r; /* red */
SANE_Int ld_shift_g; /* green */
SANE_Int ld_shift_b; /* blue */
/* default gamma table */
SANE_Word gamma[256];
SANE_Int buttons; /* number of buttons for the scanner */
char *button_name[11]; /* option names for buttons */
char *button_title[11]; /* option titles for buttons */
SANE_Word flags; /* allow per model behaviour control */
} Rts8891_Model;
struct Rts8891_Device
{
/**< Next device in linked list */
struct Rts8891_Device *next;
/**< USB device number for libusb */
SANE_Int devnum;
SANE_String file_name;
Rts8891_Model *model; /* points to a structure that decribes model specifics */
SANE_Int sensor; /* sensor id */
SANE_Bool initialized; /* true if device has been intialized */
SANE_Bool needs_warming; /* true if device needs warming up */
/* values detected during find origin */
/* TODO these are currently unused after detection */
SANE_Int left_offset; /* pixels to skip to be on left start of the scanning area */
SANE_Int top_offset; /* lines to skip to be at top of the scanning area */
/* gains from calibration */
SANE_Int red_gain;
SANE_Int green_gain;
SANE_Int blue_gain;
/* offsets from calibration */
SANE_Int red_offset;
SANE_Int green_offset;
SANE_Int blue_offset;
/* actual dpi used at hardware level may differ from the one
* at SANE level */
SANE_Int xdpi;
SANE_Int ydpi;
/* the effective scan area at hardware level may be different from
* the one at the SANE level*/
SANE_Int lines; /* lines to scan */
SANE_Int pixels; /* width of scan area */
SANE_Int bytes_per_line; /* number of bytes per line */
SANE_Int xstart; /* x start coordinate */
SANE_Int ystart; /* y start coordinate */
/* line distance shift for the active scan */
SANE_Int lds_r;
SANE_Int lds_g;
SANE_Int lds_b;
/* threshold to give 0/1 nit in lineart */
SANE_Int threshold;
/* max value from lds_r, lds_g and lds_b */
SANE_Int lds_max;
/* amount of data needed to correct ripple effect at highest dpi */
SANE_Int ripple;
/* register set of the scanner */
SANE_Int reg_count;
SANE_Byte regs[255];
/* shading calibration data */
SANE_Byte *shading_data;
/* data buffer read from scanner */
SANE_Byte *scanned_data;
/* size of the buffer */
SANE_Int data_size;
/* start of the data within scanned data */
SANE_Byte *start;
/* current pointer within scanned data */
SANE_Byte *current;
/* end of the data buffer */
SANE_Byte *end;
/* amount of bytes read from scanner */
SANE_Int read;
/* total amount of bytes to read for the scan */
SANE_Int to_read;
};
/*
* This struct is used to build a static list of USB IDs and link them
* to a struct that describes the corresponding model.
*/
typedef struct Rts8891_USB_Device_Entry
{
SANE_Word vendor_id; /**< USB vendor identifier */
SANE_Word product_id; /**< USB product identifier */
Rts8891_Model *model; /**< Scanner model information */
} Rts8891_USB_Device_Entry;
/* this function init the rts8891 library */
void rts8891_lib_init (void);
/***********************************/
/* RTS8891 ASIC specific functions */
/***********************************/
/* this functions commits pending scan command */
static SANE_Status rts8891_commit (SANE_Int devnum, SANE_Byte value);
/**
* move the head backward by a huge line number then poll home sensor until
* head has get back home
*/
static SANE_Status rts8891_park (SANE_Int devnum, SANE_Byte * regs);
#endif /* not RTS8891_LOW_H */

Wyświetl plik

@ -0,0 +1,858 @@
/* sane - Scanner Access Now Easy.
Copyright (C) 2007-2008 stef.dev@free.fr
This file is part of the SANE package.
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.
*/
/* this file contains functions common to rts88xx ASICs */
#include "sane/config.h"
#include "sane/sane.h"
#include "sane/sanei_backend.h"
#include "sane/sanei_usb.h"
#include "rts88xx_lib.h"
#include <stdio.h>
#include <sys/time.h>
#define RTS88XX_LIB_BUILD 2
/* init rts88xx library */
void
sanei_rts88xx_lib_init (void)
{
DBG_INIT ();
DBG (DBG_info, "RTS88XX library, version %d.%d-rc-%d\n", V_MAJOR, V_MINOR,
RTS88XX_LIB_BUILD);
}
/*
* registers helpers to avoid direct access
*/
SANE_Bool
sanei_rts88xx_is_color (SANE_Byte * regs)
{
if ((regs[0x2f] & 0x11) == 0x11)
return SANE_TRUE;
return SANE_FALSE;
}
void
sanei_rts88xx_set_gray_scan (SANE_Byte * regs)
{
regs[0x2f] = (regs[0x2f] & 0x0f) | 0x20;
}
void
sanei_rts88xx_set_color_scan (SANE_Byte * regs)
{
regs[0x2f] = (regs[0x2f] & 0x0f) | 0x10;
}
void
sanei_rts88xx_set_offset (SANE_Byte * regs, SANE_Byte red, SANE_Byte green,
SANE_Byte blue)
{
/* offset for odd pixels */
regs[0x02] = red;
regs[0x03] = green;
regs[0x04] = blue;
/* offset for even pixels */
regs[0x05] = red;
regs[0x06] = green;
regs[0x07] = blue;
}
void
sanei_rts88xx_set_gain (SANE_Byte * regs, SANE_Byte red, SANE_Byte green,
SANE_Byte blue)
{
regs[0x08] = red;
regs[0x09] = green;
regs[0x0a] = blue;
}
void
sanei_rts88xx_set_scan_frequency (SANE_Byte * regs, int frequency)
{
regs[0x64] = (regs[0x64] & 0xf0) | (frequency & 0x0f);
}
/*
* read one register at given index
*/
SANE_Status
sanei_rts88xx_read_reg (SANE_Int devnum, SANE_Int index, SANE_Byte * reg)
{
SANE_Status status = SANE_STATUS_GOOD;
unsigned char cmd[] = { 0x80, 0x00, 0x00, 0x01 };
size_t size;
cmd[1] = index;
size = 4;
status = sanei_usb_write_bulk (devnum, cmd, &size);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sanei_rts88xx_read_reg: bulk write failed\n");
return status;
}
size = 1;
status = sanei_usb_read_bulk (devnum, reg, &size);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sanei_rts88xx_read_reg: bulk read failed\n");
return status;
}
DBG (DBG_io2, "sanei_rts88xx_read_reg: reg[0x%02x]=0x%02x\n", index, *reg);
return status;
}
/*
* write one register at given index
*/
SANE_Status
sanei_rts88xx_write_reg (SANE_Int devnum, SANE_Int index, SANE_Byte * reg)
{
SANE_Status status = SANE_STATUS_GOOD;
unsigned char cmd[] = { 0x88, 0x00, 0x00, 0x01, 0xff };
size_t size;
cmd[1] = index;
cmd[4] = *reg;
size = 5;
status = sanei_usb_write_bulk (devnum, cmd, &size);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sanei_rts88xx_write_reg: bulk write failed\n");
return status;
}
DBG (DBG_io2, "sanei_rts88xx_write_reg: reg[0x%02x]=0x%02x\n", index, *reg);
return status;
}
/*
* write length consecutive registers, starting at index
* register 0xb3 is never wrote in bulk register write, so we split
* write if it belongs to the register set sent
*/
SANE_Status
sanei_rts88xx_write_regs (SANE_Int devnum, SANE_Int start,
SANE_Byte * source, SANE_Int length)
{
size_t size = 0;
size_t i;
SANE_Byte buffer[260];
char message[256 * 5];
if (DBG_LEVEL > DBG_io)
{
for (i = 0; i < (size_t) length; i++)
{
sprintf (message + 5 * i, "0x%02x ", source[i]);
}
DBG (DBG_io, "sanei_rts88xx_write_regs : write_regs(0x%02x,%d)=%s\n",
start, length, message);
}
/* when writing several registers at a time, we avoid writing the 0xb3 register
* which is used to control the status of the scanner */
if ((start + length > 0xb3) && (length > 1))
{
size = 0xb3 - start;
buffer[0] = 0x88;
buffer[1] = start;
buffer[2] = 0x00;
buffer[3] = size;
for (i = 0; i < size; i++)
buffer[i + 4] = source[i];
/* the USB block is size + 4 bytes of header long */
size += 4;
if (sanei_usb_write_bulk (devnum, buffer, &size) != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"sanei_rts88xx_write_regs : write registers part 1 failed ...\n");
return SANE_STATUS_IO_ERROR;
}
/* skip 0xb3 register */
size -= 3;
start = 0xb4;
source = source + size;
}
size = length - size;
buffer[0] = 0x88;
buffer[1] = start;
buffer[2] = 0x00;
buffer[3] = size;
for (i = 0; i < size; i++)
buffer[i + 4] = source[i];
/* the USB block is size + 4 bytes of header long */
size += 4;
if (sanei_usb_write_bulk (devnum, buffer, &size) != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"sanei_rts88xx_write_regs : write registers part 2 failed ...\n");
return SANE_STATUS_IO_ERROR;
}
return SANE_STATUS_GOOD;
}
/* read several registers starting at the given index */
SANE_Status
sanei_rts88xx_read_regs (SANE_Int devnum, SANE_Int start,
SANE_Byte * dest, SANE_Int length)
{
SANE_Status status;
static SANE_Byte command_block[] = { 0x80, 0, 0x00, 0xFF };
size_t size, i;
char message[256 * 5];
if (start + length > 255)
{
DBG (DBG_error,
"sanei_rts88xx_read_regs: start and length must be within [0..255]\n");
return SANE_STATUS_INVAL;
}
/* write header */
size = 4;
command_block[1] = start;
command_block[3] = length;
status = sanei_usb_write_bulk (devnum, command_block, &size);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sanei_rts88xx_read_regs: failed to write header\n");
return status;
}
/* read data */
size = length;
status = sanei_usb_read_bulk (devnum, dest, &size);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sanei_rts88xx_read_regs: failed to read data\n");
return status;
}
if (size != (size_t) length)
{
DBG (DBG_warn, "sanei_rts88xx_read_regs: read got only %d bytes\n",
size);
}
if (DBG_LEVEL >= DBG_io)
{
for (i = 0; i < size; i++)
sprintf (message + 5 * i, "0x%02x ", dest[i]);
DBG (DBG_io, "sanei_rts88xx_read_regs: read_regs(0x%02x,%d)=%s\n",
start, length, message);
}
return status;
}
/*
* get status by reading registers 0x10 and 0x11
*/
SANE_Status
sanei_rts88xx_get_status (SANE_Int devnum, SANE_Byte * regs)
{
SANE_Status status;
status = sanei_rts88xx_read_regs (devnum, 0x10, regs + 0x10, 2);
DBG (DBG_io, "sanei_rts88xx_get_status: get_status()=0x%02x 0x%02x\n",
regs[0x10], regs[0x11]);
return status;
}
/*
* set status by writing registers 0x10 and 0x11
*/
SANE_Status
sanei_rts88xx_set_status (SANE_Int devnum, SANE_Byte * regs,
SANE_Byte reg10, SANE_Byte reg11)
{
SANE_Status status;
regs[0x10] = reg10;
regs[0x11] = reg11;
status = sanei_rts88xx_write_regs (devnum, 0x10, regs + 0x10, 2);
DBG (DBG_io, "sanei_rts88xx_set_status: 0x%02x 0x%02x\n", regs[0x10],
regs[0x11]);
return status;
}
/*
* get lamp status by reading registers 0x84 to 0x8f, only 0x8F is currently usefull
* 0x84 and following could "on" timers
*/
SANE_Status
sanei_rts88xx_get_lamp_status (SANE_Int devnum, SANE_Byte * regs)
{
SANE_Status status;
status = sanei_rts88xx_read_regs (devnum, 0x84, regs + 0x84, 11);
return status;
}
/* resets lamp */
SANE_Status
sanei_rts88xx_reset_lamp (SANE_Int devnum, SANE_Byte * regs)
{
SANE_Status status;
SANE_Byte reg;
/* read the 0xda register, then clear lower nibble and write it back */
status = sanei_rts88xx_read_reg (devnum, 0xda, &reg);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"sanei_rts88xx_reset_lamp: failed to read 0xda register\n");
return status;
}
reg = 0xa0;
status = sanei_rts88xx_write_reg (devnum, 0xda, &reg);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"sanei_rts88xx_reset_lamp: failed to write 0xda register\n");
return status;
}
/* on cleared, get status */
status = sanei_rts88xx_get_status (devnum, regs);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sanei_rts88xx_reset_lamp: failed to get status\n");
return status;
}
DBG (DBG_io, "sanei_rts88xx_reset_lamp: status=0x%02x 0x%02x\n", regs[0x10],
regs[0x11]);
/* set low nibble to 7 and write it */
reg = reg | 0x07;
status = sanei_rts88xx_write_reg (devnum, 0xda, &reg);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"sanei_rts88xx_reset_lamp: failed to write 0xda register\n");
return status;
}
status = sanei_rts88xx_read_reg (devnum, 0xda, &reg);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"sanei_rts88xx_reset_lamp: failed to read 0xda register\n");
return status;
}
if (reg != 0xa7)
{
DBG (DBG_warn,
"sanei_rts88xx_reset_lamp: expected reg[0xda]=0xa7, got 0x%02x\n",
reg);
}
return status;
}
/*
* get lcd status by reading registers 0x20, 0x21 and 0x22
*/
SANE_Status
sanei_rts88xx_get_lcd (SANE_Int devnum, SANE_Byte * regs)
{
SANE_Status status;
status = sanei_rts88xx_read_regs (devnum, 0x20, regs + 0x20, 3);
DBG (DBG_io, "sanei_rts88xx_get_lcd: 0x%02x 0x%02x 0x%02x\n", regs[0x20],
regs[0x21], regs[0x22]);
return status;
}
/*
* write to special control register CONTROL_REG=0xb3
*/
SANE_Status
sanei_rts88xx_write_control (SANE_Int devnum, SANE_Byte value)
{
SANE_Status status;
status = sanei_rts88xx_write_reg (devnum, CONTROL_REG, &value);
return status;
}
/*
* send the cancel control sequence
*/
SANE_Status
sanei_rts88xx_cancel (SANE_Int devnum)
{
SANE_Status status;
status = sanei_rts88xx_write_control (devnum, 0x02);
if (status != SANE_STATUS_GOOD)
return status;
status = sanei_rts88xx_write_control (devnum, 0x02);
if (status != SANE_STATUS_GOOD)
return status;
status = sanei_rts88xx_write_control (devnum, 0x00);
if (status != SANE_STATUS_GOOD)
return status;
status = sanei_rts88xx_write_control (devnum, 0x00);
return status;
}
/*
* write the given number of bytes pointed by value into memory
* length is payload length
* extra is number of bytes to add to the usb write length
*/
SANE_Status
sanei_rts88xx_write_mem (SANE_Int devnum, SANE_Int length, SANE_Int extra,
SANE_Byte * value)
{
SANE_Status status;
SANE_Byte *buffer;
size_t i, size;
char message[(0xFFC0 + 10) * 3] = "";
buffer = (SANE_Byte *) malloc (length + 10);
memset (buffer, 0, length + 10);
if (buffer == NULL)
return SANE_STATUS_NO_MEM;
buffer[0] = 0x89;
buffer[1] = 0x00;
buffer[2] = HIBYTE (length);
buffer[3] = LOBYTE (length);
for (i = 0; i < (size_t) length; i++)
{
buffer[i + 4] = value[i];
if (DBG_LEVEL > DBG_io2)
{
sprintf (message + 3 * i, "%02x ", buffer[i + 4]);
}
}
DBG (DBG_io, "sanei_rts88xx_write_mem: %02x %02x %02x %02x -> %s\n",
buffer[0], buffer[1], buffer[2], buffer[3], message);
size = length + 4 + extra;
status = sanei_usb_write_bulk (devnum, buffer, &size);
free (buffer);
if ((status == SANE_STATUS_GOOD) && (size != (size_t) length + 4 + extra))
{
DBG (DBG_error,
"sanei_rts88xx_write_mem: only wrote %d bytes out of %d\n", size,
length + 4);
status = SANE_STATUS_IO_ERROR;
}
return status;
}
/*
* set memory with the given data
*/
SANE_Status
sanei_rts88xx_set_mem (SANE_Int devnum, SANE_Byte ctrl1,
SANE_Byte ctrl2, SANE_Int length, SANE_Byte * value)
{
SANE_Status status;
SANE_Byte regs[2];
regs[0] = ctrl1;
regs[1] = ctrl2;
status = sanei_rts88xx_write_regs (devnum, 0x91, regs, 2);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"sanei_rts88xx_set_mem: failed to write 0x91/0x92 registers\n");
return status;
}
status = sanei_rts88xx_write_mem (devnum, length, 0, value);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sanei_rts88xx_set_mem: failed to write memory\n");
}
return status;
}
/*
* read length bytes of memory into area pointed by value
*/
SANE_Status
sanei_rts88xx_read_mem (SANE_Int devnum, SANE_Int length, SANE_Byte * value)
{
SANE_Status status;
size_t size, read, want;
SANE_Byte header[4];
/* build and write length header */
header[0] = 0x81;
header[1] = 0x00;
header[2] = HIBYTE (length);
header[3] = LOBYTE (length);
size = 4;
status = sanei_usb_write_bulk (devnum, header, &size);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"sanei_rts88xx_read_mem: failed to write length header\n");
return status;
}
DBG (DBG_io, "sanei_rts88xx_read_mem: %02x %02x %02x %02x -> ...\n",
header[0], header[1], header[2], header[3]);
read = 0;
while (length > 0)
{
if (length > 2048)
want = 2048;
else
want = length;
size = want;
status = sanei_usb_read_bulk (devnum, value + read, &size);
if (size != want)
{
DBG (DBG_error,
"sanei_rts88xx_read_mem: only read %d bytes out of %d\n", size,
want);
status = SANE_STATUS_IO_ERROR;
}
length -= size;
read += size;
}
return status;
}
/*
* set memory with the given data
*/
SANE_Status
sanei_rts88xx_get_mem (SANE_Int devnum, SANE_Byte ctrl1,
SANE_Byte ctrl2, SANE_Int length, SANE_Byte * value)
{
SANE_Status status;
SANE_Byte regs[2];
regs[0] = ctrl1;
regs[1] = ctrl2;
status = sanei_rts88xx_write_regs (devnum, 0x91, regs, 2);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"sanei_rts88xx_get_mem: failed to write 0x91/0x92 registers\n");
return status;
}
status = sanei_rts88xx_read_mem (devnum, length, value);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sanei_rts88xx_get_mem: failed to read memory\n");
}
return status;
}
/*
* write to the nvram controler
*/
SANE_Status
sanei_rts88xx_nvram_ctrl (SANE_Int devnum, SANE_Int length, SANE_Byte * value)
{
SANE_Status status = SANE_STATUS_GOOD;
SANE_Int size = 0;
SANE_Int i;
SANE_Byte buffer[60];
char message[60 * 5];
if (DBG_LEVEL > DBG_io)
{
for (i = 0; i < length; i++)
{
sprintf (message + 5 * i, "0x%02x ", value[i]);
}
DBG (DBG_io, "sanei_rts88xx_nvram_ctrl : nvram_ctrl(0x00,%d)=%s\n",
length, message);
}
buffer[0] = 0x8a;
buffer[1] = 0x00;
buffer[2] = 0x00;
buffer[3] = length;
for (i = 0; i < size; i++)
buffer[i + 4] = value[i];
/* the USB block is size + 4 bytes of header long */
size = length + 4;
#ifdef HAZARDOUS_EXPERIMENT
status = sanei_usb_write_bulk (devnum, buffer, &size);
#else
devnum = devnum;
status = SANE_STATUS_GOOD;
#endif
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sanei_rts88xx_nvram_ctrl : write failed ...\n");
}
return status;
}
/*
* setup nvram
*/
SANE_Status
sanei_rts88xx_setup_nvram (SANE_Int devnum, SANE_Int length,
SANE_Byte * value)
{
SANE_Status status = SANE_STATUS_GOOD;
SANE_Byte local[2], reg;
int i;
status = sanei_rts88xx_nvram_ctrl (devnum, length, value);
#ifndef HAZARDOUS_EXPERIMENT
return SANE_STATUS_GOOD;
#endif
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sanei_rts88xx_setup_nvram : failed step #1 ...\n");
return status;
}
local[0] = 0x18;
local[1] = 0x08;
for (i = 0; i < 8; i++)
{
status = sanei_rts88xx_nvram_ctrl (devnum, 2, local);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sanei_rts88xx_setup_nvram : failed loop #%d ...\n",
i);
return status;
}
status = sanei_rts88xx_read_reg (devnum, 0x10, &reg);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"sanei_rts88xx_setup_nvram : register reading failed loop #%d ...\n",
i);
return status;
}
DBG (DBG_io, "sanei_rts88xx_setup_nvram: reg[0x10]=0x%02x\n", reg);
}
reg = 0;
status = sanei_rts88xx_write_reg (devnum, CONTROLER_REG, &reg);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"sanei_rts88xx_setup_nvram : controler register write failed\n");
return status;
}
reg = 1;
status = sanei_rts88xx_write_reg (devnum, CONTROLER_REG, &reg);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"sanei_rts88xx_setup_nvram : controler register write failed\n");
return status;
}
return status;
}
/*
* Sets scan area, no checks are being done, so watch your steps
*/
void
sanei_rts88xx_set_scan_area (SANE_Byte * regs, SANE_Int ystart,
SANE_Int yend, SANE_Int xstart, SANE_Int xend)
{
/* vertical lines to move before scan */
regs[START_LINE] = LOBYTE (ystart);
regs[START_LINE + 1] = HIBYTE (ystart);
/* total number of line to move */
regs[END_LINE] = LOBYTE (yend);
regs[END_LINE + 1] = HIBYTE (yend);
/* set horizontal start position */
regs[START_PIXEL] = LOBYTE (xstart);
regs[START_PIXEL + 1] = HIBYTE (xstart);
/* set horizontal end position */
regs[END_PIXEL] = LOBYTE (xend);
regs[END_PIXEL + 1] = HIBYTE (xend);
}
/**
* read available data count from scanner
* from tests it appears that advertised data
* may not be really available, and that a pause must be made
* before reading data so that it is really there.
* Such as reading data twice.
*/
SANE_Status
sanei_rts88xx_data_count (SANE_Int devnum, SANE_Word * count)
{
SANE_Status status;
size_t size;
static SANE_Byte header[4] = { 0x90, 0x00, 0x00, 3 };
SANE_Byte result[3];
/* set count in case of failure */
*count = 0;
size = 4;
status = sanei_usb_write_bulk (devnum, header, &size);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sanei_rts88xx_data_count : failed to write header\n");
return status;
}
size = 3;
status = sanei_usb_read_bulk (devnum, result, &size);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error,
"sanei_rts88xx_data_count : failed to read data count\n");
return status;
}
*count = result[0] + (result[1] << 8) + (result[2] << 16);
DBG (DBG_io2, "sanei_rts88xx_data_count: %d bytes available (0x%06x)\n",
*count, *count);
return status;
}
/**
* Waits for data being available while optionally polling motor. There is a timeout
* to prevent scanner waiting forever non coming data.
*/
SANE_Status
sanei_rts88xx_wait_data (SANE_Int devnum, SANE_Bool busy, SANE_Word * count)
{
SANE_Status status;
SANE_Byte control;
/* poll the available byte count until not 0 */
while (SANE_TRUE)
{
status = sanei_rts88xx_data_count (devnum, count);
if (*count != 0)
{
DBG (DBG_io, "sanei_rts88xx_wait_data: %d bytes available\n",
*count);
return SANE_STATUS_GOOD;
}
/* check that the scanner is busy scanning */
if (busy)
{
sanei_rts88xx_read_reg (devnum, CONTROL_REG, &control);
if ((control & 0x08) == 0 && (*count == 0))
{
DBG (DBG_error,
"sanei_rts88xx_wait_data: scanner stopped being busy before data are available\n");
return SANE_STATUS_IO_ERROR;
}
}
}
/* we hit timeout */
return SANE_STATUS_IO_ERROR;
}
/*
* read scanned data from scanner up to the size given. The actual length read is returned.
*/
SANE_Status
sanei_rts88xx_read_data (SANE_Int devnum, SANE_Word * length,
unsigned char *dest)
{
SANE_Status status = SANE_STATUS_GOOD;
SANE_Byte header[4];
size_t size, len, remain, read;
/* do not read too much data */
if (*length > RTS88XX_MAX_XFER_SIZE)
len = RTS88XX_MAX_XFER_SIZE;
else
len = *length;
/* write command header first */
header[0] = 0x91;
header[1] = 0x00;
header[2] = HIBYTE (len);
header[3] = LOBYTE (len);
size = 4;
status = sanei_usb_write_bulk (devnum, header, &size);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sanei_rts88xx_read_data: failed to write header\n");
}
read = 0;
/* first read blocks aligned on 64 bytes boundary */
while (len - read > 64)
{
size = (len - read) & 0xFFC0;
status = sanei_usb_read_bulk (devnum, dest + read, &size);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sanei_rts88xx_read_data: failed to read data\n");
return status;
}
DBG (DBG_io2, "sanei_rts88xx_read_data: read %d bytes\n", size);
read += size;
}
/* then read remainder */
remain = len - read;
if (remain > 0)
{
status = sanei_usb_read_bulk (devnum, dest + read, &remain);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sanei_rts88xx_read_data: failed to read data\n");
return status;
}
DBG (DBG_io2, "sanei_rts88xx_read_data: read %d bytes\n", remain);
read += remain;
}
/* update actual read length */
DBG (DBG_io, "sanei_rts88xx_read_data: read %d bytes, %d required\n",
read, *length);
*length = read;
return status;
}

Wyświetl plik

@ -0,0 +1,213 @@
/* sane - Scanner Access Now Easy.
Copyright (C) 2007-2008 stef.dev@free.fr
This file is part of the SANE package.
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 RTS88XX_LIB_H
#define RTS88XX_LIB_H
#include "sane/sane.h"
#include "sane/sanei_usb.h"
#include "unistd.h"
#include "string.h"
/* TODO put his in a place where it can be reused */
#define DBG_error0 0 /* errors/warnings printed even with debuglevel 0 */
#define DBG_error 1 /* fatal errors */
#define DBG_init 2 /* initialization and scanning time messages */
#define DBG_warn 3 /* warnings and non-fatal errors */
#define DBG_info 4 /* informational messages */
#define DBG_proc 5 /* starting/finishing functions */
#define DBG_io 6 /* io functions */
#define DBG_io2 7 /* io functions that are called very often */
#define DBG_data 8 /* log data sent and received */
/*
* defines for registers name
*/
#define CONTROL_REG 0xb3
#define CONTROLER_REG 0x1d
/* geometry registers */
#define START_LINE 0x60
#define END_LINE 0x62
#define START_PIXEL 0x66
#define END_PIXEL 0x6c
#define RTS88XX_MAX_XFER_SIZE 0xFFC0
#define LOBYTE(x) ((u_int8_t)((x) & 0xFF))
#define HIBYTE(x) ((u_int8_t)((x) >> 8))
/* this function init the rts88xx library */
void sanei_rts88xx_lib_init (void);
SANE_Bool sanei_rts88xx_is_color (SANE_Byte * regs);
void sanei_rts88xx_set_gray_scan (SANE_Byte * regs);
void sanei_rts88xx_set_color_scan (SANE_Byte * regs);
void sanei_rts88xx_set_offset (SANE_Byte * regs, SANE_Byte red,
SANE_Byte green, SANE_Byte blue);
void sanei_rts88xx_set_gain (SANE_Byte * regs, SANE_Byte red, SANE_Byte green,
SANE_Byte blue);
void sanei_rts88xx_set_scan_frequency (SANE_Byte * regs, int frequency);
/*
* set scan area
*/
void sanei_rts88xx_set_scan_area (SANE_Byte * reg, SANE_Int ystart,
SANE_Int yend, SANE_Int xstart,
SANE_Int xend);
/*
* read one register at given index
*/
SANE_Status sanei_rts88xx_read_reg (SANE_Int devnum, SANE_Int index,
SANE_Byte * reg);
/*
* read scanned data from scanner up to the size given. The actual length read is returned.
*/
SANE_Status sanei_rts88xx_read_data (SANE_Int devnum, SANE_Word * length,
unsigned char *dest);
/*
* write one register at given index
*/
SANE_Status sanei_rts88xx_write_reg (SANE_Int devnum, SANE_Int index,
SANE_Byte * reg);
/*
* write length consecutive registers, starting at index
* register 0xb3 is never wrote in bulk register write, so we split
* write if it belongs to the register set sent
*/
SANE_Status sanei_rts88xx_write_regs (SANE_Int devnum, SANE_Int start,
SANE_Byte * source, SANE_Int length);
/* read several registers starting at the given index */
SANE_Status sanei_rts88xx_read_regs (SANE_Int devnum, SANE_Int start,
SANE_Byte * dest, SANE_Int length);
/*
* get status by reading registers 0x10 and 0x11
*/
SANE_Status sanei_rts88xx_get_status (SANE_Int devnum, SANE_Byte * regs);
/*
* set status by writing registers 0x10 and 0x11
*/
SANE_Status sanei_rts88xx_set_status (SANE_Int devnum, SANE_Byte * regs,
SANE_Byte reg10, SANE_Byte reg11);
/*
* get lamp status by reading registers 0x84 to 0x8d
*/
SANE_Status sanei_rts88xx_get_lamp_status (SANE_Int devnum, SANE_Byte * regs);
/* reset lamp */
SANE_Status sanei_rts88xx_reset_lamp (SANE_Int devnum, SANE_Byte * regs);
/* get lcd panel status */
SANE_Status sanei_rts88xx_get_lcd (SANE_Int devnum, SANE_Byte * regs);
/*
* write to special control register CONTROL_REG=0xb3
*/
SANE_Status sanei_rts88xx_write_control (SANE_Int devnum, SANE_Byte value);
/*
* send the cancel control sequence
*/
SANE_Status sanei_rts88xx_cancel (SANE_Int devnum);
/*
* read available data count from scanner
*/
SANE_Status sanei_rts88xx_data_count (SANE_Int devnum, SANE_Word * count);
/*
* wait for scanned data to be available, if busy is true, check is scanner is busy
* while waiting. The number of data bytes of available data is returned in 'count'.
*/
SANE_Status sanei_rts88xx_wait_data (SANE_Int devnum, SANE_Bool busy,
SANE_Word * count);
/*
* write the given number of bytes pointed by value into memory
*/
SANE_Status sanei_rts88xx_write_mem (SANE_Int devnum, SANE_Int length,
SANE_Int extra, SANE_Byte * value);
/*
* set memory with the given data
*/
SANE_Status sanei_rts88xx_set_mem (SANE_Int devnum, SANE_Byte ctrl1,
SANE_Byte ctrl2, SANE_Int length,
SANE_Byte * value);
/*
* read the given number of bytes from memory into buffer
*/
SANE_Status sanei_rts88xx_read_mem (SANE_Int devnum, SANE_Int length,
SANE_Byte * value);
/*
* get memory
*/
SANE_Status sanei_rts88xx_get_mem (SANE_Int devnum, SANE_Byte ctrl1,
SANE_Byte ctrl2, SANE_Int length,
SANE_Byte * value);
/*
* write to the nvram controler
*/
SANE_Status sanei_rts88xx_nvram_ctrl (SANE_Int devnum, SANE_Int length,
SANE_Byte * value);
/*
* setup nvram
*/
SANE_Status sanei_rts88xx_setup_nvram (SANE_Int devnum, SANE_Int length,
SANE_Byte * value);
/* does a simple scan, putting data in image */
/* SANE_Status sanei_rts88xx_simple_scan (SANE_Int devnum, SANE_Byte * regs, int regcount, SANE_Word size, unsigned char *image); */
#endif /* not RTS88XX_LIB_H */

2
configure vendored
Wyświetl plik

@ -27050,7 +27050,7 @@ echo "$as_me: Manually selected backends: ${BACKENDS}" >&6;}
hp hp3500 hp3900 hp4200 hp5400 hp5590 hpljm1005 hs2p \
ibm leo lexmark \
ma1509 matsushita microtek microtek2 mustek mustek_usb \
nec niash pie pixma plustek ricoh \
nec niash pie pixma plustek ricoh rts8891 \
s9036 sceptre sharp sm3600 sm3840 snapscan sp15c st400 stv680 \
tamarack teco1 teco2 teco3 test u12 umax umax_pp umax1220u"

Wyświetl plik

@ -366,7 +366,7 @@ else
hp hp3500 hp3900 hp4200 hp5400 hp5590 hpljm1005 hs2p \
ibm leo lexmark \
ma1509 matsushita microtek microtek2 mustek mustek_usb \
nec niash pie pixma plustek ricoh \
nec niash pie pixma plustek ricoh rts8891 \
s9036 sceptre sharp sm3600 sm3840 snapscan sp15c st400 stv680 \
tamarack teco1 teco2 teco3 test u12 umax umax_pp umax1220u"

Wyświetl plik

@ -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?).
:backend "rts8891" ; name of backend
:version "1.0-0" ; version of backend (or "unmaintained")
:manpage "rts8891" ; name of manpage (if it exists)
:url "http://stef.dev.free.fr/sane/rts8891/index.html"
; backend's web page
:comment "This backend supports Realtek RTS8891 ASIC bases scanners."
; comment about the backend
:devicetype :scanner ; start of a list of devices....
; other types: :stillcam, :vidcam,
; :meta, :api
:mfg "UMAX" ; name a manufacturer
:url "http://www.umax.com.tw/" ; manufacturer's URL
:model "Astra 4400"
:interface "USB"
:usbid "0x1606" "0x0070"
:status :good
:comment "Supports 75, 150, 300, 600 and 1200 dpi"
:model "Astra 4450"
:interface "USB"
:usbid "0x1606" "0x0070"
:status :untested
:mfg "Hewlett-Packard" ; name a manufacturer
:url "http://www.hp.com/"
:model "scanjet 4470c"
:interface "USB"
:usbid "0x03f0" "0x0805"
:status :good
:comment "re-branded Astra 4400"

Wyświetl plik

@ -2517,20 +2517,6 @@
:status :unsupported
:comment "Not supported, to be added to genesys backend."
:model "Astra 4400"
:url "/unsupported/umax-astra-4400.html"
:interface "USB"
:usbid "0x1606" "0x0070"
:status :unsupported
:comment "Probably not supported. See link for details."
:model "Astra 4450"
:url "/unsupported/umax-astra-4450.html"
:interface "USB"
:usbid "0x1606" "0x0070"
:status :unsupported
:comment "Probably not supported. See link for details."
:model "Astra 4500"
:url "/unsupported/umax-astra-4500.html"
:interface "USB"

Wyświetl plik

@ -0,0 +1,198 @@
.\" .IX sane-rts8891
.TH "sane-rts8891" "5" "16 March 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy"
.SH "NAME"
sane\-rts8891 \- SANE backend for Umax Astra 4400/4450 and Hewlett-Packard Scanjet 4470c scanners
.SH "DESCRIPTION"
The
.B sane\-rts8891
library implements a SANE (Scanner Access Now Easy) backend that
provides access to scanner based on Realtek RTS8891 ASIC.
.PP
The scanners that should work with this backend are:
.PP
.RS
.ft CR
.nf
Vendor Model status
\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-
Umax 4400 good
Umax 4450 untested
HP 4470c good re-badged Astra 4400
.fi
.ft R
.RE
The options the backend supports can either be selected through
command line options to programs like scanimage or through GUI
elements in xscanimage or xsane.
.br
If you have any strange behavior, please report to the backend
maintainer or to the SANE mailing list.
Valid command line options and their syntax can be listed by using
.RS
scanimage \-\-help \-d rts8891
.RE
.TP
.B Scan Mode Options
.TP
.B \-\-mode
selects the basic mode of operation of the scanner valid choices are
.I auto
.R ,
.I Color
.R ,
.I Gray
and
.I Lineart
The default or automatic mode is Color. The Lineart mode is black and white only (1 bit).
Grayscale will produce 256 levels of gray (8 bits). Gray and Lineart mode are emulated.
Color mode allows for over 16 million different colors produced from 24 bits of color information.
.TP
.B \-\-resolution
selects the resolution for a scan. The horizontal and vertical resolutions are set
by the value of this option. Default value is 150 dpi, automatic value is 75 dpi.
The scanner is capable of the following resolutions for the specified option value:
.PP
.RS
.ft CR
.nf
Value Hor. Resolution Vert. Resolution
\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
75 75dpi 150dpi lines are averaged to match dpi
150 150dpi 150dpi
300 300dpi 300dpi
600 600dpi 600dpi
1200 1200dpi 600dpi lines are duplicated to match dpi
.fi
.ft R
.RE
.TP
.B \-\-preview
requests a preview scan. The resolution used for that scan is 75 dpi
and the scan area and the scan mode are as specified through their options,
or the default if not specified. The default and automatic value for preview mode is "no".
.TP
.B Image Enhancement Options
.TP
.B \-\-threshold
selects the minimum\-brightness to get a white point. The threshold is only used with Lineart mode scans.
It is specified as a percentage in the range 0..100% (in steps of 1).
The default or automatic value of the threshold option is 50.
.TP
.B --custom-gamma
allows the user to specify a gamma table (see gamma-table options). The default and automatic
value is 'no'.
.TP
.B --gamma-table
(gray and lineart modes) can be used to download a user defined
gamma table for the gray channel. The table must be 256 SANE_Word long.
Valid values are in the [0..255] range.
The automatic or default value is a builtin gamma table. This option
is active only if custom-gamma is set to yes.
.TP
.B --red-gamma-table
(color mode only) can be used to download a user defined
gamma table for the red channel. The table must be 256 SANE_Word long.
Valid values are in the [0..255] range.
The automatic or default value is a builtin gamma table. This option
is active only if custom-gamma is set to yes.
.TP
.B --green-gamma-table
(color mode only) can be used to download a user defined
gamma table for the green channel. The table must be 256 SANE_Word long.
Valid values are in the [0..255] range.
The automatic or default value is a builtin gamma table. This option
is active only if custom-gamma is set to yes.
.TP
.B --blue-gamma-table
(color mode only) can be used to download a user defined gamma table
for the blue channel. The table must be 256 SANE_Word long.
Valid values are in the [0..255] range.
The automatic or default value is a builtin gamma table. This option
is active only if custom-gamma is set to yes.
.TP
.B Utility Options
.TP
.B \-\-lamp\-on
this advanced option switches the lamp on. It is a set only option.
.TP
.B \-\-lamp\-off
this advanced option switches the lamp off. It is a set only option.
.SH "CONFIGURATION FILE"
The configuration file @CONFIGDIR@/rts8891.conf contains only the usb device id (eg usb 0x043d 0x007c).
.SH "FILES"
.TP
.I @LIBDIR@/libsane\-rts8891.a
The static library implementing this backend.
.TP
.I @LIBDIR@/libsane\-rts8891.so
The shared library implementing this backend (present on systems that
support dynamic loading).
.SH "ENVIRONMENT"
.TP
.B SANE_DEBUG_RTS88XX_LIB
rts88xx library debugging messages control.
.TP
.B SANE_DEBUG_RTS8891_LOW
rts8891 low-level access debugging messages control.
.TP
.B SANE_DEBUG_RTS8891
rts8891 backend debugging messages control.
.br
.br
If the library or backend was compiled with debug support enabled, these
environment variables controls the debug level for this backend. E.g.,
a value of 255 requests all debug output to be printed. Smaller levels
reduce verbosity. Higher levels of debugging also gives PNM files holding
data scanned at various stages of calibration and during final scan. In case
you find a bug and want ot report about it, it is recommended to reproduce
the bug whit these values set to 255, and join the debugging output to the
report.
.SH "LIMITATIONS"
There is no support for transparency adaptor.
.SH "BUGS"
.br
No bugs are currently known. In case you find a bug, you may report it to the maintainer,
the sane-devel mailing list or fill a bug report at
https://alioth.debian.org/tracker/?atid=410366&group_id=30186&func=browse
.SH "SEE ALSO"
sane\-usb(5), scanimage(1), xscanimage(1), xsane(1), sane(7)
.SH "AUTHOR"
.TP
This backend is currently developped by Stéphane Voltz.
.I http://stef.dev.free.fr/sane/rts8891
.SH "CREDITS"
.TP
Many thanks go to:
Laurent Fournier who lent me his scanjet 4470c.
Henry Wieland for the time spent recording USB activity and testing the experimental version.
The ASIC registers analysis by Troy Rollo and Johannes Hub did provide me of some important
hints on the operation of the RTS8891.