kopia lustrzana https://gitlab.com/sane-project/backends
Added gt68xx backend for scanners based on the Grandtech GT-6801
and GT-8616 chips like The Mustek BearPaw CU, and TA scanners and some Artec Ultima 2000 clones.DEVEL_2_0_BRANCH-1
rodzic
5a61a1f8ac
commit
492b63060f
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
|||
2002-10-25 Henning Meier-Geinitz <henning@meier-geinitz.de>
|
||||
|
||||
* backend/Makefile.in backend/dll.conf backend/gt68xx.c
|
||||
backend/gt68xx.conf backend/gt68xx.h backend/gt68xx_devices.c
|
||||
backend/gt68xx_generic.c backend/gt68xx_generic.h
|
||||
backend/gt68xx_gt6801.c backend/gt68xx_gt6801.h
|
||||
backend/gt68xx_gt6816.c backend/gt68xx_gt6816.h backend/gt68xx_high.c
|
||||
backend/gt68xx_high.h backend/gt68xx_low.c backend/gt68xx_low.h
|
||||
backend/gt68xx_mid.c backend/gt68xx_mid.h
|
||||
backend/gt68xx_shm_channel.c backend/gt68xx_shm_channel.h:
|
||||
Added gt68xx backend for scanners based on the Grandtech GT-6801
|
||||
and GT-8616 chips like The Mustek BearPaw CU, and TA scanners
|
||||
and some Artec Ultima 2000 clones.
|
||||
|
||||
2002-10-24 Peter Fales <peter@fales-lorenz.net>
|
||||
|
||||
* backend/gphoto2.c: Improve checks for values specified in config
|
||||
|
|
|
@ -61,10 +61,11 @@ DISTCLEAN_FILES = @DISTCLEAN_FILES@
|
|||
|
||||
PRELOADABLE_BACKENDS = abaton agfafocus apple artec as6e avision bh canon \
|
||||
canon630u @CANON_PP@ coolscan coolscan2 dc25 @DC210@ @DC240@ dmc \
|
||||
epson fujitsu @GPHOTO2@ hp @HPSJ5S@ leo matsushita microtek microtek2 \
|
||||
mustek mustek_pp mustek_usb nec @NET@ pie @PINT@ plustek \
|
||||
epson fujitsu @GPHOTO2@ gt68xx hp @HPSJ5S@ leo matsushita microtek \
|
||||
microtek2 mustek mustek_pp mustek_usb nec @NET@ pie @PINT@ plustek \
|
||||
@PNM@ @QCAM@ ricoh s9036 sceptre sharp @SM3600@ @SNAPSCAN@ \
|
||||
sp15c st400 tamarack test teco1 teco2 teco3 umax umax_pp umax1220u @V4L@
|
||||
sp15c st400 tamarack test teco1 teco2 teco3 umax umax_pp umax1220u \
|
||||
@V4L@
|
||||
ifneq (@SELECTED_BACKENDS@,)
|
||||
PRELOADABLE_BACKENDS = @SELECTED_BACKENDS@
|
||||
endif
|
||||
|
@ -95,9 +96,15 @@ DISTFILES = abaton.c abaton.conf abaton.h agfafocus.c agfafocus.conf \
|
|||
dc210.c dc210.conf dc210.h \
|
||||
dc240.c dc240.conf dc240.h dc25.c dc25.conf dc25.h djpeg.c djpeg.README \
|
||||
dll.aliases dll.c dll.conf dmc.c dmc.conf dmc.h \
|
||||
epson.c epson_scsi.c epson_usb.c epson.conf epson.h epson_scsi.h epson_usb.h \
|
||||
epson.c epson_scsi.c epson_usb.c epson.conf epson.h epson_scsi.h \
|
||||
epson_usb.h \
|
||||
fujitsu.c fujitsu.conf fujitsu.h fujitsu-scsi.h \
|
||||
gphoto2.c gphoto2.conf gphoto2.h hp-accessor.c hp-accessor.h hp.c hp.conf \
|
||||
gphoto2.c gphoto2.conf gphoto2.h \
|
||||
gt68xx.c gt68xx.h gt68xx_high.c gt68xx_high.h gt68xx_mid.c gt68xx_mid.h \
|
||||
gt68xx_gt6801.c gt68xx_gt6801.h gt68xx_gt6816.c gt68xx_gt6816.h \
|
||||
gt68xx_low.c gt68xx_low.h gt68xx_devices.c gt68xx_generic.c \
|
||||
gt68xx_generic.h \
|
||||
hp-accessor.c hp-accessor.h hp.c hp.conf \
|
||||
hp-device.c hp-device.h hp.h hp-handle.c hp-handle.h hp-hpmem.c hp-option.c \
|
||||
hp-option.h hp.README hp-scl.c hp-scl.h hp-scsi.h hp.TODO \
|
||||
hpsj5s.c hpsj5s.conf hpsj5s.h \
|
||||
|
@ -293,6 +300,8 @@ libsane-fujitsu.la: ../sanei/sanei_config2.lo
|
|||
libsane-fujitsu.la: ../sanei/sanei_constrain_value.lo
|
||||
libsane-fujitsu.la: ../sanei/sanei_scsi.lo
|
||||
libsane-gphoto2.la: ../sanei/sanei_constrain_value.lo djpeg.lo
|
||||
libsane-gt68xx.la: ../sanei/sanei_constrain_value.lo
|
||||
libsane-gt68xx.la: ../sanei/sanei_usb.lo
|
||||
libsane-hp.la: ../sanei/sanei_config2.lo
|
||||
libsane-hp.la: ../sanei/sanei_constrain_value.lo
|
||||
libsane-hp.la: ../sanei/sanei_scsi.lo
|
||||
|
|
|
@ -18,6 +18,7 @@ coolscan2
|
|||
dmc
|
||||
epson
|
||||
fujitsu
|
||||
gt68xx
|
||||
hp
|
||||
hpsj5s
|
||||
leo
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,65 @@
|
|||
# gt68xx.conf: Configuration file for GT68XX based scanners
|
||||
# Read man sane-gt68xx for documentation
|
||||
|
||||
##############################################################################
|
||||
# Autodetect Mustek BearPaw 1200 CU, 2400 CU, Mustek ScanExpress 1200 UB Plus,
|
||||
# Artec Ultima 2000, and several other GT-6801-based scanners
|
||||
usb 0x05d8 0x4002
|
||||
|
||||
# Mustek BearPaw 1200 CU doesn't need any override
|
||||
|
||||
# Mustek ScanExpress 1200 UB Plus, Medion/Lifetec/Tevion LT 9452, Trust
|
||||
# Compact Scan USB 19200 use that one:
|
||||
#override "mustek-scanexpress-1200-ub-plus"
|
||||
#vendor "Lifetec"
|
||||
#model "LT 9452"
|
||||
#vendor "Trust"
|
||||
#model "Compact Scan USB 19200"
|
||||
|
||||
# Artec Ultima 2000, Boeder SmartScan Slim Edition,
|
||||
# Medion/Lifetec/Tevion/Cytron MD/LT 9385 and MD 9458,
|
||||
# Trust Flat Scan USB 19200
|
||||
#override "artec-ultima-2000"
|
||||
#firmware "ePlus2k.usb"
|
||||
#vendor "Boeder"
|
||||
#model "SmartScan Slim Edition"
|
||||
#vendor "Medion"
|
||||
#model "MD/LT 9385"
|
||||
#model "MD 9458"
|
||||
#vendor "Trust"
|
||||
#model "Flat Scan USB 19200"
|
||||
|
||||
# Mustek BearPaw 2400 CU
|
||||
#override "mustek-bearpaw-2400-cu"
|
||||
|
||||
##############################################################################
|
||||
# Autodetect Mustek BearPaw 1200 TA and Mustek BearPaw 1200 CS
|
||||
usb 0x055f 0x021e
|
||||
#model "Bearpaw 1200 CS"
|
||||
|
||||
##############################################################################
|
||||
# Autodetect Mustek BearPaw 2400 TA and Mustek BearPaw 2400 CS
|
||||
usb 0x055f 0x0218
|
||||
#model "Bearpaw 2400 CS"
|
||||
|
||||
##############################################################################
|
||||
# Autodetect Mustek BearPaw 2400 TA Plus
|
||||
usb 0x055f 0x0219
|
||||
|
||||
##############################################################################
|
||||
# Autodetect Mustek BearPaw 2400 CU Plus
|
||||
usb 0x055f 0x021d
|
||||
|
||||
##############################################################################
|
||||
# Autodetect Mustek Bearpaw 1200 CU Plus and Packard Bell Diamond 1200
|
||||
usb 0x055f 0x021c
|
||||
#vendor "Packard Bell"
|
||||
#model "Diamond 1200"
|
||||
|
||||
##############################################################################
|
||||
# Autodetect Mustek ScanExpress A3 USB
|
||||
usb 0x055f 0x0210
|
||||
|
||||
##############################################################################
|
||||
# Autodetect Lexmark X70/X73
|
||||
usb 0x043d 0x002d
|
|
@ -0,0 +1,56 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2002 Sergey Vlasov <vsu@altlinux.ru>
|
||||
|
||||
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 GT68XX_H
|
||||
#define GT68XX_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "gt68xx_high.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 GT68XX_CONFIG_FILE "gt68xx.conf"
|
||||
|
||||
#endif /* not GT68XX_H */
|
|
@ -0,0 +1,623 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2002 Sergey Vlasov <vsu@altlinux.ru>
|
||||
Copyright (C) 2002 Henning Meier-Geinitz <henning@meier-geinitz.de>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/* Scanner-specific data */
|
||||
|
||||
#include "gt68xx_low.h"
|
||||
#include "gt68xx_generic.c"
|
||||
#include "gt68xx_gt6801.c"
|
||||
#include "gt68xx_gt6816.c"
|
||||
|
||||
/* Default parameters for the analog frontend (offset, gain) */
|
||||
|
||||
static GT68xx_AFE_Parameters default_afe_params = {
|
||||
0x14, 0x07, 0x14, 0x07, 0x14, 0x07
|
||||
};
|
||||
|
||||
static GT68xx_AFE_Parameters mustek_2400ta_afe_params = {
|
||||
0x2a, 0x0c, 0x2e, 0x06, 0x2d, 0x07
|
||||
};
|
||||
|
||||
static GT68xx_AFE_Parameters mustek_1200ta_afe_params = {
|
||||
0x2a, 0x0c, 0x2e, 0x06, 0x2d, 0x07
|
||||
};
|
||||
|
||||
static GT68xx_AFE_Parameters mustek_1200cu_afe_params = {
|
||||
0x14, 0x06, 0x15, 0x08, 0x11, 0x04
|
||||
};
|
||||
|
||||
/* Default exposure times */
|
||||
static GT68xx_Exposure_Parameters default_exposure_params = {
|
||||
0x157, 0x157, 0x157
|
||||
};
|
||||
|
||||
static GT68xx_Command_Set mustek_gt6816_command_set = {
|
||||
"mustek-gt6816",
|
||||
|
||||
0x200c, 0x200b,
|
||||
0x2010, 0x3f40, 0x2011, 0x3f00,
|
||||
0x2012, 0x3f40, 0x2013, 0x3f00,
|
||||
|
||||
/* activate */ NULL,
|
||||
/* deactivate */ NULL,
|
||||
gt6816_check_firmware,
|
||||
gt6816_download_firmware,
|
||||
gt6816_get_power_status,
|
||||
gt6816_get_ta_status,
|
||||
gt6816_lamp_control,
|
||||
gt6816_is_moving,
|
||||
gt68xx_generic_move_relative,
|
||||
gt6816_carriage_home,
|
||||
gt68xx_generic_start_scan,
|
||||
gt68xx_generic_read_scanned_data,
|
||||
gt6816_stop_scan,
|
||||
gt6816_setup_scan,
|
||||
gt68xx_generic_set_afe,
|
||||
gt68xx_generic_set_exposure_time,
|
||||
gt68xx_generic_get_id
|
||||
};
|
||||
|
||||
static GT68xx_Command_Set mustek_gt6801_command_set = {
|
||||
"mustek-gt6801",
|
||||
|
||||
0x200a, 0x2009,
|
||||
0x2010, 0x3f40, 0x2011, 0x3f00,
|
||||
0x2012, 0x3f40, 0x2013, 0x3f00,
|
||||
|
||||
/* activate */ NULL,
|
||||
/* deactivate */ NULL,
|
||||
gt6801_check_firmware,
|
||||
gt6801_download_firmware,
|
||||
gt6801_get_power_status,
|
||||
/* get_ta_status (FIXME: implement this) */ NULL,
|
||||
gt6801_lamp_control,
|
||||
gt6801_is_moving,
|
||||
/*gt68xx_generic_move_relative *** to be tested */ NULL,
|
||||
gt6801_carriage_home,
|
||||
gt68xx_generic_start_scan,
|
||||
gt68xx_generic_read_scanned_data,
|
||||
gt6801_stop_scan,
|
||||
gt6801_setup_scan,
|
||||
gt68xx_generic_set_afe,
|
||||
gt68xx_generic_set_exposure_time,
|
||||
gt68xx_generic_get_id
|
||||
};
|
||||
|
||||
static GT68xx_Model mustek_2400ta_model = {
|
||||
"mustek-bearpaw-2400-ta",
|
||||
"Mustek",
|
||||
"BearPaw 2400 TA",
|
||||
"A2fw.usb",
|
||||
SANE_FALSE,
|
||||
|
||||
&mustek_gt6816_command_set,
|
||||
|
||||
1200,
|
||||
2400,
|
||||
1200, /* ??? */
|
||||
1200,
|
||||
1200,
|
||||
SANE_FALSE,
|
||||
{1200, 600, 300, 150, 100, 50, 0},
|
||||
{2400, 1200, 600, 300, 150, 100, 50, 0},
|
||||
{16, 12, 8, 0},
|
||||
{16, 12, 8, 0},
|
||||
SANE_FIX (3.67),
|
||||
SANE_FIX (7.4),
|
||||
SANE_FIX (219.0),
|
||||
SANE_FIX (298.0),
|
||||
SANE_FIX (0.0),
|
||||
SANE_FIX (0.635),
|
||||
|
||||
SANE_FIX (94.0),
|
||||
SANE_FIX (107.0),
|
||||
SANE_FIX (37.0),
|
||||
SANE_FIX (165.0),
|
||||
SANE_FIX (95.0),
|
||||
|
||||
0, 24, 48, /* ??? */
|
||||
0,
|
||||
|
||||
COLOR_ORDER_RGB,
|
||||
&mustek_2400ta_afe_params,
|
||||
&default_exposure_params,
|
||||
SANE_FALSE,
|
||||
0
|
||||
/* flatbed values tested */
|
||||
};
|
||||
|
||||
static GT68xx_Model mustek_2400taplus_model = {
|
||||
"mustek-bearpaw-2400-ta-plus",
|
||||
"Mustek",
|
||||
"BearPaw 2400 TA Plus",
|
||||
"A2Dfw.usb",
|
||||
SANE_FALSE,
|
||||
|
||||
&mustek_gt6816_command_set,
|
||||
|
||||
1200,
|
||||
2400,
|
||||
600,
|
||||
1200,
|
||||
1200,
|
||||
SANE_FALSE,
|
||||
{1200, 600, 300, 100, 50, 0},
|
||||
{2400, 1200, 600, 300, 100, 50, 0},
|
||||
{8, 0},
|
||||
{16, 12, 8, 0},
|
||||
SANE_FIX (7.41),
|
||||
SANE_FIX (7.4),
|
||||
SANE_FIX (219.0),
|
||||
SANE_FIX (298.0),
|
||||
SANE_FIX (0.0),
|
||||
SANE_FIX (5.0),
|
||||
|
||||
SANE_FIX (94.0),
|
||||
SANE_FIX (107.0),
|
||||
SANE_FIX (37.0),
|
||||
SANE_FIX (165.0),
|
||||
SANE_FIX (95.0),
|
||||
|
||||
0, 48, 96,
|
||||
8,
|
||||
|
||||
COLOR_ORDER_RGB,
|
||||
&mustek_2400ta_afe_params,
|
||||
&default_exposure_params,
|
||||
SANE_FALSE,
|
||||
0
|
||||
/* Setup and tested */
|
||||
};
|
||||
|
||||
|
||||
static GT68xx_Model mustek_1200ta_model = {
|
||||
"mustek-bearpaw-1200-ta",
|
||||
"Mustek",
|
||||
"BearPaw 1200 TA",
|
||||
"A1fw.usb",
|
||||
SANE_FALSE,
|
||||
|
||||
&mustek_gt6816_command_set,
|
||||
|
||||
600,
|
||||
1200,
|
||||
600,
|
||||
600,
|
||||
1200,
|
||||
SANE_TRUE,
|
||||
{600, 300, 150, 75, 50, 0},
|
||||
{1200, 600, 300, 150, 100, 50, 0},
|
||||
{16, 12, 8, 0},
|
||||
{16, 12, 8, 0},
|
||||
SANE_FIX (8.4),
|
||||
SANE_FIX (7.5),
|
||||
SANE_FIX (220.0),
|
||||
SANE_FIX (299.0),
|
||||
SANE_FIX (0.0),
|
||||
SANE_FIX (7.0),
|
||||
|
||||
SANE_FIX (98.0),
|
||||
SANE_FIX (108.0), /* 109 */
|
||||
SANE_FIX (37.0),
|
||||
SANE_FIX (163.0),
|
||||
SANE_FIX (95.0),
|
||||
|
||||
32, 16, 0, /* ??? */
|
||||
0,
|
||||
|
||||
COLOR_ORDER_RGB,
|
||||
&mustek_1200ta_afe_params,
|
||||
&default_exposure_params,
|
||||
SANE_FALSE,
|
||||
0
|
||||
/* Everything untested */
|
||||
};
|
||||
|
||||
static GT68xx_Model mustek_1200cuplus_model = {
|
||||
"mustek-bearpaw-1200-cu-plus",
|
||||
"Mustek",
|
||||
"Bearpaw 1200 CU Plus",
|
||||
"PS1Dfw.usb",
|
||||
SANE_FALSE,
|
||||
|
||||
&mustek_gt6816_command_set,
|
||||
|
||||
600,
|
||||
1200,
|
||||
600,
|
||||
600,
|
||||
1200,
|
||||
SANE_FALSE,
|
||||
{600, 300, 150, 75, 50, 0},
|
||||
{1200, 600, 300, 150, 75, 50, 0},
|
||||
{16, 12, 8, 0},
|
||||
{16, 12, 8, 0},
|
||||
SANE_FIX (0.0),
|
||||
SANE_FIX (13.0),
|
||||
SANE_FIX (217.0),
|
||||
SANE_FIX (299.0),
|
||||
SANE_FIX (5.0),
|
||||
SANE_FIX (0.0), /* no black mark */
|
||||
|
||||
SANE_FIX (0.0), /* no TA */
|
||||
SANE_FIX (0.0),
|
||||
SANE_FIX (100.0),
|
||||
SANE_FIX (100.0),
|
||||
SANE_FIX (0.0),
|
||||
|
||||
0, 0, 0,
|
||||
0,
|
||||
|
||||
COLOR_ORDER_BGR,
|
||||
&default_afe_params,
|
||||
&default_exposure_params,
|
||||
SANE_TRUE,
|
||||
0
|
||||
/* Everything untested */
|
||||
};
|
||||
|
||||
static GT68xx_Model mustek_2400cuplus_model = {
|
||||
"mustek-bearpaw-2400-cu-plus",
|
||||
"Mustek",
|
||||
"BearPaw 2400 CU Plus",
|
||||
"PS2Dfw.usb",
|
||||
SANE_FALSE,
|
||||
|
||||
&mustek_gt6816_command_set,
|
||||
|
||||
1200,
|
||||
2400,
|
||||
1200,
|
||||
1200,
|
||||
1200,
|
||||
SANE_FALSE,
|
||||
{1200, 600, 300, 200, 150, 100, 50, 0},
|
||||
{2400, 1200, 600, 300, 200, 150, 100, 50, 0},
|
||||
{16, 12, 8, 0},
|
||||
{16, 12, 8, 0},
|
||||
SANE_FIX (2.0),
|
||||
SANE_FIX (13.0),
|
||||
SANE_FIX (217.0),
|
||||
SANE_FIX (300.0),
|
||||
SANE_FIX (5.0),
|
||||
SANE_FIX (0.0), /* no black mark */
|
||||
|
||||
SANE_FIX (0.0), /* no TA */
|
||||
SANE_FIX (0.0),
|
||||
SANE_FIX (100.0),
|
||||
SANE_FIX (100.0),
|
||||
SANE_FIX (0.0),
|
||||
|
||||
0, 0, 0, /* no LD correction */
|
||||
0,
|
||||
|
||||
COLOR_ORDER_BGR,
|
||||
&default_afe_params,
|
||||
&default_exposure_params,
|
||||
SANE_TRUE,
|
||||
0
|
||||
/* Setup and tested */
|
||||
};
|
||||
|
||||
/* Seems that Mustek ScanExpress 1200 UB Plus, the Mustek BearPaw 1200 CU
|
||||
* and lots of other scanners have the same USB identifier.
|
||||
*/
|
||||
static GT68xx_Model mustek_1200cu_model = {
|
||||
"mustek-bearpaw-1200-cu",
|
||||
"Mustek",
|
||||
"BearPaw 1200 CU",
|
||||
"PS1fw.usb",
|
||||
SANE_FALSE,
|
||||
|
||||
&mustek_gt6801_command_set,
|
||||
|
||||
600,
|
||||
1200,
|
||||
600,
|
||||
600,
|
||||
1200,
|
||||
SANE_TRUE,
|
||||
{600, 300, 150, 75, 50, 0},
|
||||
{1200, 600, 300, 150, 75, 50, 0},
|
||||
{12, 8, 0},
|
||||
{12, 8, 0},
|
||||
SANE_FIX (0.0),
|
||||
SANE_FIX (13.0),
|
||||
SANE_FIX (217.0),
|
||||
SANE_FIX (299.0),
|
||||
SANE_FIX (3.5),
|
||||
SANE_FIX (0.0), /* no black mark */
|
||||
|
||||
SANE_FIX (0.0), /* no TA */
|
||||
SANE_FIX (0.0),
|
||||
SANE_FIX (100.0),
|
||||
SANE_FIX (100.0),
|
||||
SANE_FIX (0.0),
|
||||
|
||||
0, 0, 0, /* no LD correction */
|
||||
0,
|
||||
|
||||
COLOR_ORDER_BGR,
|
||||
&mustek_1200cu_afe_params,
|
||||
&default_exposure_params,
|
||||
SANE_TRUE,
|
||||
0
|
||||
/* Setup and tested */
|
||||
};
|
||||
|
||||
static GT68xx_Model mustek_scanexpress1200ubplus_model = {
|
||||
"mustek-scanexpress-1200-ub-plus",
|
||||
"Mustek",
|
||||
"ScanExpress 1200 UB Plus",
|
||||
"SBfw.usb",
|
||||
SANE_FALSE,
|
||||
|
||||
&mustek_gt6801_command_set,
|
||||
|
||||
600,
|
||||
1200,
|
||||
600,
|
||||
600,
|
||||
1200,
|
||||
SANE_TRUE,
|
||||
{600, 300, 150, 75, 50, 0},
|
||||
{1200, 600, 300, 150, 75, 50, 0},
|
||||
{12, 8, 0},
|
||||
{12, 8, 0},
|
||||
SANE_FIX (0.0),
|
||||
SANE_FIX (15.5),
|
||||
SANE_FIX (217.0),
|
||||
SANE_FIX (299.0),
|
||||
SANE_FIX (6.5),
|
||||
SANE_FIX (0.0), /* no black mark */
|
||||
|
||||
SANE_FIX (0.0), /* no TA */
|
||||
SANE_FIX (0.0),
|
||||
SANE_FIX (100.0),
|
||||
SANE_FIX (100.0),
|
||||
SANE_FIX (0.0),
|
||||
|
||||
0, 0, 0, /* no LD correction */
|
||||
0,
|
||||
|
||||
COLOR_ORDER_BGR,
|
||||
&mustek_1200cu_afe_params,
|
||||
&default_exposure_params,
|
||||
SANE_TRUE,
|
||||
0
|
||||
/* Setup and tested */
|
||||
};
|
||||
|
||||
static GT68xx_Model artec_ultima2000_model = {
|
||||
"artec-ultima-2000",
|
||||
"Artec",
|
||||
"Ultima 2000",
|
||||
"Gt680xfw.usb",
|
||||
SANE_FALSE,
|
||||
|
||||
&mustek_gt6801_command_set,
|
||||
|
||||
600,
|
||||
600,
|
||||
600,
|
||||
600,
|
||||
600,
|
||||
SANE_TRUE,
|
||||
{600, 300, 200, 150, 100, 75, 50, 0},
|
||||
{600, 300, 200, 150, 100, 75, 50, 0},
|
||||
{12, 8, 0},
|
||||
{12, 8, 0},
|
||||
SANE_FIX (2.0),
|
||||
SANE_FIX (7.0),
|
||||
SANE_FIX (218.0),
|
||||
SANE_FIX (299.0),
|
||||
SANE_FIX (0.0),
|
||||
SANE_FIX (0.0), /* no black mark */
|
||||
SANE_FIX (0.0), /* no TA */
|
||||
SANE_FIX (0.0),
|
||||
SANE_FIX (100.0),
|
||||
SANE_FIX (100.0),
|
||||
SANE_FIX (0.0),
|
||||
|
||||
0, 0, 0, /* no LD correction */
|
||||
0,
|
||||
|
||||
COLOR_ORDER_BGR,
|
||||
&mustek_1200cu_afe_params,
|
||||
&default_exposure_params,
|
||||
SANE_TRUE,
|
||||
GT68XX_FLAG_MIRROR_X | GT68XX_FLAG_MOTOR_HOME | GT68XX_FLAG_OFFSET_INV
|
||||
/* Setup for Cytron TCM MD 9385 */
|
||||
};
|
||||
|
||||
static GT68xx_Model mustek_2400cu_model = {
|
||||
"mustek-bearpaw-2400-cu",
|
||||
"Mustek",
|
||||
"BearPaw 2400 CU",
|
||||
"PS2fw.usb",
|
||||
SANE_FALSE,
|
||||
|
||||
&mustek_gt6801_command_set,
|
||||
|
||||
1200,
|
||||
2400,
|
||||
1200,
|
||||
1200,
|
||||
2400,
|
||||
SANE_TRUE,
|
||||
{1200, 600, 300, 150, 100, 50, 0},
|
||||
{2400, 1200, 600, 300, 150, 100, 50, 0},
|
||||
{12, 8, 0},
|
||||
{12, 8, 0},
|
||||
SANE_FIX (0.0), /* 0 */
|
||||
SANE_FIX (13.5), /* 1280, */
|
||||
SANE_FIX (215.9), /* 10240, */
|
||||
SANE_FIX (296.7), /* 28032, */
|
||||
SANE_FIX (5.5),
|
||||
SANE_FIX (0.0), /* no black mark */
|
||||
|
||||
SANE_FIX (0.0), /* no TA */
|
||||
SANE_FIX (0.0),
|
||||
SANE_FIX (100.0),
|
||||
SANE_FIX (100.0),
|
||||
SANE_FIX (0.0),
|
||||
|
||||
0, 0, 0, /* no LD correction */
|
||||
0,
|
||||
|
||||
COLOR_ORDER_BGR,
|
||||
&mustek_1200cu_afe_params,
|
||||
&default_exposure_params,
|
||||
SANE_TRUE,
|
||||
0
|
||||
/* basically tested, works up to 300 dpi (?) */
|
||||
};
|
||||
|
||||
static GT68xx_Model mustek_a3usb_model = {
|
||||
"mustek-scanexpress-a3-usb",
|
||||
"Mustek",
|
||||
"ScanExpress A3 USB",
|
||||
"A32fw.usb",
|
||||
SANE_FALSE,
|
||||
|
||||
&mustek_gt6816_command_set,
|
||||
|
||||
300,
|
||||
600,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
SANE_FALSE,
|
||||
{300, 150, 95, 50, 0},
|
||||
{600, 300, 150, 75, 50, 0},
|
||||
{12, 8, 0},
|
||||
{12, 8, 0},
|
||||
SANE_FIX (2.0),
|
||||
SANE_FIX (13.0),
|
||||
SANE_FIX (300.0),
|
||||
SANE_FIX (420.0),
|
||||
SANE_FIX (5.0),
|
||||
SANE_FIX (0.0), /* no black mark */
|
||||
|
||||
SANE_FIX (0.0), /* no TA */
|
||||
SANE_FIX (0.0),
|
||||
SANE_FIX (100.0),
|
||||
SANE_FIX (100.0),
|
||||
SANE_FIX (0.0),
|
||||
|
||||
0, 0, 0, /* no LD correction */
|
||||
0,
|
||||
|
||||
COLOR_ORDER_BGR,
|
||||
&default_afe_params,
|
||||
&default_exposure_params,
|
||||
SANE_TRUE,
|
||||
0
|
||||
/* Completely untested */
|
||||
};
|
||||
|
||||
static GT68xx_Model lexmark_x73_model = {
|
||||
"lexmark-x73",
|
||||
"Lexmark",
|
||||
"X73",
|
||||
"OSLO3071b2.usb",
|
||||
SANE_FALSE,
|
||||
|
||||
&mustek_gt6816_command_set,
|
||||
|
||||
600,
|
||||
1200,
|
||||
600,
|
||||
600, /* ??? */
|
||||
1200, /* ??? */
|
||||
SANE_TRUE,
|
||||
|
||||
{600, 300, 150, 75, 50, 0},
|
||||
{1200, 600, 300, 150, 75, 50, 0},
|
||||
{16, 12, 8, 0},
|
||||
{16, 12, 8, 0},
|
||||
SANE_FIX (6.519),
|
||||
SANE_FIX (12.615),
|
||||
SANE_FIX (220.0), /* physical windowsize: 220 mm */
|
||||
SANE_FIX (300.0), /* physical windowsize: 300 mm */
|
||||
SANE_FIX (1.0),
|
||||
SANE_FIX (0.0),
|
||||
|
||||
SANE_FIX (0.0), /* no TA */
|
||||
SANE_FIX (0.0),
|
||||
SANE_FIX (100.0),
|
||||
SANE_FIX (100.0),
|
||||
SANE_FIX (0.0), /* ld_shift */
|
||||
|
||||
32, 16, 0,
|
||||
0,
|
||||
|
||||
COLOR_ORDER_RGB,
|
||||
&default_afe_params,
|
||||
&default_exposure_params,
|
||||
SANE_FALSE,
|
||||
0
|
||||
/* 50 dpi and 1200 dpi scan does not work (for lexmark x70); when using
|
||||
automatic gain pictures are too dark. Only some ad hoc tests for
|
||||
lexmark x70 were done so far. WARNING: Don't use the Full scan option
|
||||
with the above settings, otherwise the sensor may bump at the end of
|
||||
the sledge and the scanner may be damaged! */
|
||||
};
|
||||
|
||||
static GT68xx_USB_Device_Entry gt68xx_usb_device_list[] = {
|
||||
{0x055f, 0x0218, &mustek_2400ta_model},
|
||||
{0x055f, 0x0219, &mustek_2400taplus_model},
|
||||
{0x055f, 0x021c, &mustek_1200cuplus_model},
|
||||
{0x055f, 0x021d, &mustek_2400cuplus_model},
|
||||
{0x055f, 0x021e, &mustek_1200ta_model},
|
||||
{0x05d8, 0x4002, &mustek_1200cu_model},
|
||||
{0x05d8, 0x4002, &mustek_scanexpress1200ubplus_model}, /* manual override */
|
||||
{0x05d8, 0x4002, &artec_ultima2000_model}, /* manual override */
|
||||
{0x05d8, 0x4002, &mustek_2400cu_model}, /* manual override */
|
||||
{0x055f, 0x0210, &mustek_a3usb_model},
|
||||
{0x043d, 0x002d, &lexmark_x73_model},
|
||||
{0, 0, NULL}
|
||||
};
|
||||
|
||||
/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
|
|
@ -0,0 +1,176 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2002 Sergey Vlasov <vsu@altlinux.ru>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief GT68xx commands common for most GT68xx-based scanners.
|
||||
*/
|
||||
|
||||
#include "gt68xx_generic.h"
|
||||
|
||||
|
||||
SANE_Status
|
||||
gt68xx_generic_move_relative (GT68xx_Device * dev, SANE_Int distance)
|
||||
{
|
||||
GT68xx_Packet req;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
if (distance >= 0)
|
||||
req[0] = 0x14;
|
||||
else
|
||||
{
|
||||
req[0] = 0x15;
|
||||
distance = -distance;
|
||||
}
|
||||
req[1] = 0x01;
|
||||
req[2] = LOBYTE (distance);
|
||||
req[3] = HIBYTE (distance);
|
||||
|
||||
return gt68xx_device_req (dev, req, req);
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
gt68xx_generic_start_scan (GT68xx_Device * dev)
|
||||
{
|
||||
GT68xx_Packet req;
|
||||
SANE_Status status;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0] = 0x43;
|
||||
req[1] = 0x01;
|
||||
RIE (gt68xx_device_req (dev, req, req));
|
||||
RIE (gt68xx_device_check_result (req, 0x43));
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
gt68xx_generic_read_scanned_data (GT68xx_Device * dev, SANE_Bool * ready)
|
||||
{
|
||||
SANE_Status status;
|
||||
GT68xx_Packet req;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0] = 0x35;
|
||||
req[1] = 0x01;
|
||||
|
||||
RIE (gt68xx_device_req (dev, req, req));
|
||||
|
||||
#if 0
|
||||
/* doesn't work with gt681xfw firmware */
|
||||
if (req[1] == 0x35)
|
||||
{
|
||||
#endif
|
||||
if (req[0] == 0)
|
||||
*ready = SANE_TRUE;
|
||||
else
|
||||
*ready = SANE_FALSE;
|
||||
#if 0
|
||||
}
|
||||
else
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
#endif
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
gt68xx_generic_set_afe (GT68xx_Device * dev, GT68xx_AFE_Parameters * params)
|
||||
{
|
||||
GT68xx_Packet req;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0] = 0x22;
|
||||
req[1] = 0x01;
|
||||
req[2] = params->r_offset;
|
||||
req[3] = params->r_pga;
|
||||
req[4] = params->g_offset;
|
||||
req[5] = params->g_pga;
|
||||
req[6] = params->b_offset;
|
||||
req[7] = params->b_pga;
|
||||
|
||||
return gt68xx_device_req (dev, req, req);
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
gt68xx_generic_set_exposure_time (GT68xx_Device * dev,
|
||||
GT68xx_Exposure_Parameters * params)
|
||||
{
|
||||
GT68xx_Packet req;
|
||||
SANE_Status status;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0] = 0x76;
|
||||
req[1] = 0x01;
|
||||
req[2] = req[6] = req[10] = 0x04;
|
||||
req[4] = LOBYTE (params->r_time);
|
||||
req[5] = HIBYTE (params->r_time);
|
||||
req[8] = LOBYTE (params->g_time);
|
||||
req[9] = HIBYTE (params->g_time);
|
||||
req[12] = LOBYTE (params->b_time);
|
||||
req[13] = HIBYTE (params->b_time);
|
||||
|
||||
RIE (gt68xx_device_req (dev, req, req));
|
||||
RIE (gt68xx_device_check_result (req, 0x76));
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
gt68xx_generic_get_id (GT68xx_Device * dev)
|
||||
{
|
||||
GT68xx_Packet req;
|
||||
SANE_Status status;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0] = 0x2e;
|
||||
req[1] = 0x01;
|
||||
RIE (gt68xx_device_req (dev, req, req));
|
||||
RIE (gt68xx_device_check_result (req, 0x2e));
|
||||
|
||||
DBG (2,
|
||||
"get_id: vendor id=0x%04X, product id=0x%04X, DID=0x%08X, FID=0x%04X\n",
|
||||
req[2] + (req[3] << 8), req[4] + (req[5] << 8),
|
||||
req[6] + (req[7] << 8) + (req[8] << 16) + (req[9] << 24),
|
||||
req[10] + (req[11] << 8));
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
|
|
@ -0,0 +1,67 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2002 Sergey Vlasov <vsu@altlinux.ru>
|
||||
|
||||
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 GT68XX_GENERIC_H
|
||||
#define GT68XX_GENERIC_H
|
||||
|
||||
#include "gt68xx_low.h"
|
||||
|
||||
static SANE_Status
|
||||
gt68xx_generic_move_relative (GT68xx_Device * dev, SANE_Int distance);
|
||||
|
||||
static SANE_Status gt68xx_generic_start_scan (GT68xx_Device * dev);
|
||||
|
||||
static SANE_Status
|
||||
gt68xx_generic_read_scanned_data (GT68xx_Device * dev, SANE_Bool * ready);
|
||||
|
||||
static SANE_Status
|
||||
gt68xx_generic_set_afe (GT68xx_Device * dev, GT68xx_AFE_Parameters * params);
|
||||
|
||||
static SANE_Status
|
||||
gt68xx_generic_set_exposure_time (GT68xx_Device * dev,
|
||||
GT68xx_Exposure_Parameters * params);
|
||||
static SANE_Status gt68xx_generic_get_id (GT68xx_Device * dev);
|
||||
|
||||
#endif /* not GT68XX_GENERIC_H */
|
||||
|
||||
/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
|
|
@ -0,0 +1,646 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2002 Sergey Vlasov <vsu@altlinux.ru>
|
||||
GT6801 support by Andreas Nowack <nowack.andreas@gmx.de>
|
||||
Copyright (C) 2002 Henning Meier-Geinitz <henning@meier-geinitz.de>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief Implementation of the GT6801 specific functions.
|
||||
*/
|
||||
|
||||
#include "gt68xx_gt6801.h"
|
||||
|
||||
#if 0
|
||||
SANE_Status
|
||||
gt6801_check_firmware (GT68xx_Device * dev, SANE_Bool * loaded)
|
||||
{
|
||||
SANE_Status status;
|
||||
GT68xx_Packet req;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0] = 0x00;
|
||||
req[1] = 0x01;
|
||||
|
||||
RIE (gt68xx_device_small_req (dev, req, req));
|
||||
|
||||
/*
|
||||
* this is wrong but i do not get the right answer from the scanner....
|
||||
* should be 0x00 0x55 0x55 0x55
|
||||
*/
|
||||
if (req[0] == 0x00 && req[1] == 0x12 && req[2] == 0x00 && req[3] == 0x00)
|
||||
*loaded = SANE_TRUE;
|
||||
else
|
||||
*loaded = SANE_FALSE;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
/* doesn't work with plustek scanner */
|
||||
SANE_Status
|
||||
gt6801_check_firmware (GT68xx_Device * dev, SANE_Bool * loaded)
|
||||
{
|
||||
SANE_Status status;
|
||||
GT68xx_Packet req;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0] = 0x50;
|
||||
req[1] = 0x01;
|
||||
req[2] = 0x80;
|
||||
|
||||
RIE (gt68xx_device_req (dev, req, req));
|
||||
|
||||
if (req[0] == 0x00 && req[1] == 0x50)
|
||||
*loaded = SANE_TRUE;
|
||||
else
|
||||
*loaded = SANE_FALSE;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* doesn't work with at least cytron scanner */
|
||||
SANE_Status
|
||||
gt6801_check_firmware (GT68xx_Device * dev, SANE_Bool * loaded)
|
||||
{
|
||||
SANE_Status status;
|
||||
GT68xx_Packet req;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
|
||||
req[0] = 0x73;
|
||||
req[1] = 0x01;
|
||||
|
||||
RIE (gt68xx_device_small_req (dev, req, req));
|
||||
|
||||
/* check for correct answer */
|
||||
if ((req[0] == 0) && (req[1] == 0x12) && (req[3] != 0))
|
||||
/* req[3] is 0 if fw is not loaded, if loaded it's 0x80
|
||||
* at least on my 1284u (gerhard@gjaeger.de)
|
||||
*/
|
||||
*loaded = SANE_TRUE;
|
||||
else
|
||||
*loaded = SANE_FALSE;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define MAX_DOWNLOAD_BLOCK_SIZE 64
|
||||
|
||||
SANE_Status
|
||||
gt6801_download_firmware (GT68xx_Device * dev,
|
||||
SANE_Byte * data, SANE_Word size)
|
||||
{
|
||||
DECLARE_FUNCTION_NAME ("gt6801_download_firmware") SANE_Status status;
|
||||
SANE_Byte download_buf[MAX_DOWNLOAD_BLOCK_SIZE];
|
||||
SANE_Byte check_buf[MAX_DOWNLOAD_BLOCK_SIZE];
|
||||
SANE_Byte *block;
|
||||
SANE_Word addr, bytes_left;
|
||||
GT68xx_Packet boot_req;
|
||||
SANE_Word block_size = MAX_DOWNLOAD_BLOCK_SIZE;
|
||||
|
||||
CHECK_DEV_ACTIVE (dev, function_name);
|
||||
|
||||
for (addr = 0; addr < size; addr += block_size)
|
||||
{
|
||||
bytes_left = size - addr;
|
||||
if (bytes_left > block_size)
|
||||
block = data + addr;
|
||||
else
|
||||
{
|
||||
memset (download_buf, 0, block_size);
|
||||
memcpy (download_buf, data + addr, bytes_left);
|
||||
block = download_buf;
|
||||
}
|
||||
RIE (gt68xx_device_memory_write (dev, addr, block_size, block));
|
||||
RIE (gt68xx_device_memory_read (dev, 0x3f00, block_size, check_buf));
|
||||
|
||||
/*
|
||||
* For GT6816 this was:
|
||||
* if (memcmp (block, check_buf, block_size) != 0) ...
|
||||
* Apparently the GT6801 does something different...
|
||||
*
|
||||
* hmg: For my BP 1200 CU the result is 00 09 so maybe only the 0 is
|
||||
* relevant?
|
||||
*/
|
||||
if ((check_buf[0] != 0) && (check_buf[1] != 0x40))
|
||||
{
|
||||
XDBG ((3, "%s: mismatch at block 0x%0x\n", function_name, addr));
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
memset (boot_req, 0, sizeof (boot_req));
|
||||
boot_req[0] = 0x69;
|
||||
boot_req[1] = 0x01;
|
||||
boot_req[2] = 0xc0;
|
||||
boot_req[3] = 0x1c;
|
||||
RIE (gt68xx_device_req (dev, boot_req, boot_req));
|
||||
|
||||
#if 0
|
||||
/* hmg: the following isn't in my log: */
|
||||
memset (boot_req, 0, sizeof (boot_req)); /* I don't know if this is needed */
|
||||
boot_req[0] = 0x01;
|
||||
boot_req[1] = 0x01;
|
||||
RIE (gt68xx_device_small_req (dev, boot_req, boot_req));
|
||||
#endif
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
gt6801_get_power_status (GT68xx_Device * dev, SANE_Bool * power_ok)
|
||||
{
|
||||
SANE_Status status;
|
||||
GT68xx_Packet req;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0] = 0x10;
|
||||
req[1] = 0x01;
|
||||
|
||||
RIE (gt68xx_device_req (dev, req, req));
|
||||
|
||||
/* I don't know what power_ok = SANE_FALSE looks like... */
|
||||
/* hmg: let's assume it's different from the usual 00 10 */
|
||||
if (gt68xx_device_check_result (req, 0x10) == SANE_STATUS_GOOD)
|
||||
*power_ok = SANE_TRUE;
|
||||
else
|
||||
*power_ok = SANE_FALSE;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
gt6801_lamp_control (GT68xx_Device * dev, SANE_Bool fb_lamp,
|
||||
SANE_Bool ta_lamp)
|
||||
{
|
||||
/* this seems not to be supported by the scanner */
|
||||
(void) dev;
|
||||
(void) fb_lamp;
|
||||
(void) ta_lamp;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
gt6801_is_moving (GT68xx_Device * dev, SANE_Bool * moving)
|
||||
{
|
||||
/* this seems not to be supported by the scanner */
|
||||
(void) dev;
|
||||
|
||||
*moving = SANE_FALSE;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
gt6801_carriage_home (GT68xx_Device * dev)
|
||||
{
|
||||
GT68xx_Packet req;
|
||||
SANE_Status status;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
|
||||
if (dev->model->flags & GT68XX_FLAG_MOTOR_HOME)
|
||||
{
|
||||
req[0] = 0x34;
|
||||
req[1] = 0x01;
|
||||
status = gt68xx_device_req (dev, req, req);
|
||||
}
|
||||
else
|
||||
{
|
||||
req[0] = 0x12;
|
||||
req[1] = 0x01;
|
||||
if ((status = gt68xx_device_req (dev, req, req)) == SANE_STATUS_GOOD)
|
||||
{
|
||||
RIE (gt68xx_device_check_result (req, 0x12));
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0] = 0x24;
|
||||
req[1] = 0x01;
|
||||
status = gt68xx_device_req (dev, req, req);
|
||||
RIE (gt68xx_device_check_result (req, 0x24));
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
gt6801_stop_scan (GT68xx_Device * dev)
|
||||
{
|
||||
GT68xx_Packet req;
|
||||
SANE_Status status;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0] = 0x42;
|
||||
req[1] = 0x01;
|
||||
|
||||
RIE (gt68xx_device_req (dev, req, req));
|
||||
RIE (gt68xx_device_check_result (req, 0x42));
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/* 3.0 mm of calibration */
|
||||
#define CALIBRATION_HEIGHT 3.0
|
||||
|
||||
SANE_Status
|
||||
gt6801_setup_scan (GT68xx_Device * dev,
|
||||
GT68xx_Scan_Request * request,
|
||||
GT68xx_Scan_Action action, GT68xx_Scan_Parameters * params)
|
||||
{
|
||||
DECLARE_FUNCTION_NAME ("gt6801_setup_scan") SANE_Status status;
|
||||
GT68xx_Model *model;
|
||||
SANE_Int xdpi, ydpi;
|
||||
SANE_Bool color;
|
||||
SANE_Int depth;
|
||||
SANE_Int pixel_x0, pixel_y0, pixel_xs, pixel_ys;
|
||||
SANE_Int pixel_align;
|
||||
SANE_Int abs_x0, abs_y0, abs_xs, abs_ys, base_xdpi, base_ydpi;
|
||||
SANE_Int scan_xs, scan_ys, scan_bpl;
|
||||
SANE_Int bits_per_line;
|
||||
SANE_Byte color_mode_code;
|
||||
SANE_Bool line_mode;
|
||||
SANE_Int overscan_lines;
|
||||
SANE_Fixed x0, y0, xs, ys;
|
||||
SANE_Bool backtrack = SANE_FALSE;
|
||||
|
||||
XDBG ((5, "%s: enter (action=%s)\n", function_name,
|
||||
action == SA_CALIBRATE ? "calibrate" :
|
||||
action == SA_CALIBRATE_ONE_LINE ? "calibrate one line" :
|
||||
action == SA_SCAN ? "scan" : "calculate only"));
|
||||
|
||||
model = dev->model;
|
||||
|
||||
xdpi = request->xdpi;
|
||||
ydpi = request->ydpi;
|
||||
color = request->color;
|
||||
depth = request->depth;
|
||||
backtrack = 0;
|
||||
|
||||
base_xdpi = model->base_xdpi;
|
||||
base_ydpi = model->base_ydpi;
|
||||
|
||||
#if 0
|
||||
if (xdpi > model->base_xdpi)
|
||||
base_xdpi = model->optical_xdpi;
|
||||
#endif
|
||||
if (!model->constant_ydpi)
|
||||
{
|
||||
if (ydpi > model->base_ydpi)
|
||||
base_ydpi = model->optical_ydpi;
|
||||
}
|
||||
|
||||
XDBG ((5, "%s: base_xdpi=%d, base_ydpi=%d\n", function_name,
|
||||
base_xdpi, base_ydpi));
|
||||
|
||||
switch (action)
|
||||
{
|
||||
/* Warning: Support for TA not implemented */
|
||||
case SA_CALIBRATE_ONE_LINE:
|
||||
{
|
||||
x0 = request->x0;
|
||||
y0 = model->y_offset_calib;
|
||||
ys = SANE_FIX (1.0 * MM_PER_INCH / ydpi); /* 1 calibration line */
|
||||
xs = request->xs;
|
||||
depth = 8;
|
||||
color = SANE_TRUE;
|
||||
break;
|
||||
}
|
||||
case SA_CALIBRATE:
|
||||
{
|
||||
if (dev->model->flags & GT68XX_FLAG_MIRROR_X)
|
||||
x0 = request->x0 - model->x_offset;
|
||||
else
|
||||
x0 = request->x0 + model->x_offset;
|
||||
if (request->mbs)
|
||||
y0 = model->y_offset_calib;
|
||||
else
|
||||
y0 = 0;
|
||||
ys = SANE_FIX (CALIBRATION_HEIGHT); /* use 3 mm for calibration */
|
||||
xs = request->xs;
|
||||
color = request->color;
|
||||
break;
|
||||
}
|
||||
case SA_SCAN:
|
||||
{
|
||||
request->mbs = SANE_TRUE;
|
||||
if (dev->model->flags & GT68XX_FLAG_MIRROR_X)
|
||||
x0 = request->x0 - model->x_offset;
|
||||
else
|
||||
x0 = request->x0 + model->x_offset;
|
||||
y0 = request->y0 + model->y_offset;
|
||||
ys = request->ys;
|
||||
xs = request->xs;
|
||||
backtrack = SANE_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
XDBG ((3, "%s: invalid action=%d\n", function_name, (int) action));
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
pixel_x0 = SANE_UNFIX (x0) * xdpi / MM_PER_INCH + 0.5;
|
||||
pixel_y0 = SANE_UNFIX (y0) * ydpi / MM_PER_INCH + 0.5;
|
||||
pixel_ys = SANE_UNFIX (ys) * ydpi / MM_PER_INCH + 0.5;
|
||||
pixel_xs = SANE_UNFIX (xs) * xdpi / MM_PER_INCH + 0.5;
|
||||
|
||||
XDBG ((5, "%s: xdpi=%d, ydpi=%d\n", function_name, xdpi, ydpi));
|
||||
XDBG ((5, "%s: color=%s, depth=%d\n", function_name,
|
||||
color ? "TRUE" : "FALSE", depth));
|
||||
XDBG ((5, "%s: pixel_x0=%d, pixel_y0=%d\n", function_name,
|
||||
pixel_x0, pixel_y0));
|
||||
XDBG ((5, "%s: pixel_xs=%d, pixel_ys=%d\n", function_name,
|
||||
pixel_xs, pixel_ys));
|
||||
XDBG ((5, "%s: backtrack=%d\n", function_name, backtrack));
|
||||
|
||||
color_mode_code = 0x80; /* What does this mean ? */
|
||||
if (color)
|
||||
color_mode_code |= (1 << 2);
|
||||
else
|
||||
color_mode_code |= (1 << 1);
|
||||
|
||||
if (depth > 12)
|
||||
color_mode_code |= (1 << 5);
|
||||
else if (depth > 8)
|
||||
{
|
||||
color_mode_code &= 0x7f;
|
||||
color_mode_code |= (1 << 4);
|
||||
}
|
||||
XDBG ((5, "%s: color_mode_code = 0x%02X\n", function_name,
|
||||
color_mode_code));
|
||||
|
||||
overscan_lines = 0;
|
||||
params->ld_shift_r = params->ld_shift_g = params->ld_shift_b = 0;
|
||||
params->ld_shift_double = 0;
|
||||
|
||||
if (action == SA_SCAN && color)
|
||||
{
|
||||
/* Line distance correction is required for color scans. */
|
||||
SANE_Int optical_ydpi = model->optical_ydpi;
|
||||
SANE_Int ld_shift_r = model->ld_shift_r;
|
||||
SANE_Int ld_shift_g = model->ld_shift_g;
|
||||
SANE_Int ld_shift_b = model->ld_shift_b;
|
||||
SANE_Int max_ld = MAX (MAX (ld_shift_r, ld_shift_g), ld_shift_b);
|
||||
|
||||
overscan_lines = max_ld * ydpi / optical_ydpi;
|
||||
params->ld_shift_r = ld_shift_r * ydpi / optical_ydpi;
|
||||
params->ld_shift_g = ld_shift_g * ydpi / optical_ydpi;
|
||||
params->ld_shift_b = ld_shift_b * ydpi / optical_ydpi;
|
||||
|
||||
XDBG ((5, "%s: overscan=%d, ld=%d/%d/%d\n", function_name,
|
||||
overscan_lines, params->ld_shift_r, params->ld_shift_g,
|
||||
params->ld_shift_b));
|
||||
}
|
||||
|
||||
if (action == SA_SCAN && xdpi >= model->optical_xdpi
|
||||
&& model->ld_shift_double > 0)
|
||||
{
|
||||
params->ld_shift_double =
|
||||
model->ld_shift_double * ydpi / model->optical_ydpi;
|
||||
if (color)
|
||||
overscan_lines += (params->ld_shift_double * 3);
|
||||
else
|
||||
overscan_lines += params->ld_shift_double;
|
||||
XDBG ((5, "%s: overscan=%d, ld double=%d\n", function_name,
|
||||
overscan_lines, params->ld_shift_double));
|
||||
}
|
||||
|
||||
|
||||
XDBG ((5, "%s: base_xdpi=%d, base_ydpi=%d\n", function_name,
|
||||
base_xdpi, base_ydpi));
|
||||
|
||||
abs_x0 = pixel_x0 * base_xdpi / xdpi;
|
||||
abs_y0 = pixel_y0 * base_ydpi / ydpi;
|
||||
XDBG ((5, "%s: abs_x0=%d, abs_y0=%d\n", function_name, abs_x0, abs_y0));
|
||||
|
||||
params->double_column = abs_x0 & 1;
|
||||
|
||||
/* Calculate minimum number of pixels which span an integral multiple of 64
|
||||
* bytes. pixels must be reduced by 2 of this value if xdpi != base_dpi. */
|
||||
pixel_align = 32; /* best case for depth = 16 */
|
||||
while ((depth * pixel_align) % (64 * 8) != 0)
|
||||
pixel_align *= 2;
|
||||
XDBG ((5, "%s: pixel_align=%d\n", function_name, pixel_align));
|
||||
|
||||
if (pixel_xs % pixel_align == 0)
|
||||
scan_xs = pixel_xs;
|
||||
else
|
||||
scan_xs = (pixel_xs / pixel_align + 1) * pixel_align;
|
||||
scan_ys = pixel_ys + overscan_lines;
|
||||
|
||||
bits_per_line = depth * scan_xs;
|
||||
|
||||
/*
|
||||
if (xdpi != base_xdpi)
|
||||
scan_xs -= 2;
|
||||
*/
|
||||
if (xdpi != base_xdpi)
|
||||
abs_xs = (scan_xs - 2) * base_xdpi / xdpi;
|
||||
else
|
||||
abs_xs = scan_xs * base_xdpi / xdpi;
|
||||
|
||||
if (action == SA_CALIBRATE_ONE_LINE)
|
||||
abs_ys = 2;
|
||||
else
|
||||
abs_ys = scan_ys * base_ydpi / ydpi;
|
||||
XDBG ((5, "%s: abs_xs=%d, abs_ys=%d\n", function_name, abs_xs, abs_ys));
|
||||
|
||||
if (model->is_cis)
|
||||
{
|
||||
line_mode = SANE_TRUE;
|
||||
XDBG ((5, "%s: using line mode (CIS)\n", function_name));
|
||||
}
|
||||
else
|
||||
{
|
||||
line_mode = SANE_FALSE;
|
||||
if (!color)
|
||||
{
|
||||
XDBG ((5, "%s: using line mode for monochrome scan\n",
|
||||
function_name));
|
||||
line_mode = SANE_TRUE;
|
||||
}
|
||||
else if (ydpi >= model->ydpi_force_line_mode)
|
||||
{
|
||||
XDBG ((5, "%s: forcing line mode for ydpi=%d\n", function_name,
|
||||
ydpi));
|
||||
line_mode = SANE_TRUE;
|
||||
}
|
||||
else if (ydpi == 600 && depth == 16) /* XXX */
|
||||
{
|
||||
XDBG ((5, "%s: forcing line mode for ydpi=%d, depth=%d\n",
|
||||
function_name, ydpi, depth));
|
||||
line_mode = SANE_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (color && line_mode)
|
||||
scan_ys *= 3;
|
||||
|
||||
XDBG ((5, "%s: scan_xs=%d, scan_ys=%d\n", function_name, scan_xs, scan_ys));
|
||||
|
||||
if (color && !line_mode)
|
||||
bits_per_line *= 3;
|
||||
if (bits_per_line % 8) /* impossible */
|
||||
{
|
||||
XDBG ((0, "%s: BUG: unaligned bits_per_line=%d\n", function_name,
|
||||
bits_per_line));
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
scan_bpl = bits_per_line / 8;
|
||||
|
||||
if (scan_bpl > 15600 && !line_mode)
|
||||
{
|
||||
XDBG ((5, "%s: scan_bpl=%d, trying line mode\n", function_name,
|
||||
scan_bpl));
|
||||
line_mode = SANE_TRUE;
|
||||
if (scan_bpl % 3)
|
||||
{
|
||||
XDBG ((0, "%s: BUG: monochrome scan in pixel mode?\n",
|
||||
function_name));
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
scan_bpl /= 3;
|
||||
}
|
||||
|
||||
if (scan_bpl % 64) /* impossible */
|
||||
{
|
||||
XDBG ((0, "%s: BUG: unaligned scan_bpl=%d\n", function_name, scan_bpl));
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
if (scan_bpl > 15600)
|
||||
{
|
||||
XDBG ((3, "%s: scan_bpl=%d, too large\n", function_name, scan_bpl));
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
XDBG ((5, "%s: scan_bpl=%d\n", function_name, scan_bpl));
|
||||
|
||||
|
||||
if (!request->calculate)
|
||||
{
|
||||
GT68xx_Packet req;
|
||||
SANE_Byte motor_mode_1, motor_mode_2;
|
||||
|
||||
motor_mode_1 = (request->mbs ? 0 : 1) << 1;
|
||||
motor_mode_1 |= (request->mds ? 0 : 1) << 2;
|
||||
motor_mode_1 |= (request->mas ? 0 : 1) << 0;
|
||||
motor_mode_1 |= (backtrack ? 1 : 0) << 3;
|
||||
|
||||
motor_mode_2 = (request->lamp ? 0 : 1) << 0;
|
||||
motor_mode_2 |= (line_mode ? 0 : 1) << 2;
|
||||
XDBG ((5, "%s: motor_mode_1 = 0x%02X, motor_mode_2 = 0x%02X\n",
|
||||
function_name, motor_mode_1, motor_mode_2));
|
||||
|
||||
/* Fill in the setup command */
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0x00] = 0x20;
|
||||
req[0x01] = 0x01;
|
||||
req[0x02] = LOBYTE (abs_y0);
|
||||
req[0x03] = HIBYTE (abs_y0);
|
||||
req[0x04] = LOBYTE (abs_ys);
|
||||
req[0x05] = HIBYTE (abs_ys);
|
||||
req[0x06] = LOBYTE (abs_x0);
|
||||
req[0x07] = HIBYTE (abs_x0);
|
||||
req[0x08] = LOBYTE (abs_xs);
|
||||
req[0x09] = HIBYTE (abs_xs);
|
||||
req[0x0a] = color_mode_code;
|
||||
req[0x0b] = 0x60; /* CIS/CCD? */
|
||||
req[0x0c] = LOBYTE (xdpi);
|
||||
req[0x0d] = HIBYTE (xdpi);
|
||||
req[0x0e] = (action == SA_SCAN) ? 0x3c : 0xf0; /* ???? */
|
||||
/* hmg: doesn't seem to matter and varies for SA_SCAN */
|
||||
req[0x0f] = 0x00;
|
||||
req[0x10] = LOBYTE (scan_bpl);
|
||||
req[0x11] = HIBYTE (scan_bpl);
|
||||
req[0x12] = LOBYTE (scan_ys);
|
||||
req[0x13] = HIBYTE (scan_ys);
|
||||
req[0x14] = motor_mode_1;
|
||||
req[0x15] = motor_mode_2;
|
||||
req[0x16] = LOBYTE (ydpi);
|
||||
req[0x17] = HIBYTE (ydpi);
|
||||
if (backtrack)
|
||||
{
|
||||
if (model->is_cis)
|
||||
req[0x18] = 0x20;
|
||||
else
|
||||
req[0x18] = 0x3f;
|
||||
}
|
||||
else
|
||||
req[0x18] = 0x00;
|
||||
|
||||
status = gt68xx_device_req (dev, req, req);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
XDBG ((3, "%s: setup request failed: %s\n", function_name,
|
||||
sane_strstatus (status)));
|
||||
return status;
|
||||
}
|
||||
RIE (gt68xx_device_check_result (req, 0x20));
|
||||
}
|
||||
|
||||
/* Fill in calculated values */
|
||||
params->xdpi = xdpi;
|
||||
params->ydpi = ydpi;
|
||||
params->depth = depth;
|
||||
params->color = color;
|
||||
params->pixel_xs = pixel_xs;
|
||||
params->pixel_ys = pixel_ys;
|
||||
params->scan_xs = scan_xs;
|
||||
params->scan_ys = scan_ys;
|
||||
params->scan_bpl = scan_bpl;
|
||||
params->line_mode = line_mode;
|
||||
params->overscan_lines = overscan_lines;
|
||||
|
||||
XDBG ((6, "%s: leave: ok\n", function_name));
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
|
|
@ -0,0 +1,76 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2002 Sergey Vlasov <vsu@altlinux.ru>
|
||||
GT6801 support by Andreas Nowack <nowack.andreas@gmx.de>
|
||||
|
||||
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 GT68XX_GT6801_H
|
||||
#define GT68XX_GT6801_H
|
||||
|
||||
static SANE_Status
|
||||
gt6801_check_firmware (GT68xx_Device * dev, SANE_Bool * loaded);
|
||||
|
||||
static SANE_Status
|
||||
gt6801_download_firmware (GT68xx_Device * dev,
|
||||
SANE_Byte * data, SANE_Word size);
|
||||
|
||||
static SANE_Status
|
||||
gt6801_get_power_status (GT68xx_Device * dev, SANE_Bool * power_ok);
|
||||
|
||||
static SANE_Status
|
||||
gt6801_lamp_control (GT68xx_Device * dev, SANE_Bool fb_lamp,
|
||||
SANE_Bool ta_lamp);
|
||||
|
||||
static SANE_Status gt6801_is_moving (GT68xx_Device * dev, SANE_Bool * moving);
|
||||
|
||||
static SANE_Status gt6801_carriage_home (GT68xx_Device * dev);
|
||||
|
||||
static SANE_Status gt6801_carriage_home (GT68xx_Device * dev);
|
||||
|
||||
static SANE_Status gt6801_stop_scan (GT68xx_Device * dev);
|
||||
|
||||
static SANE_Status
|
||||
gt6801_setup_scan (GT68xx_Device * dev,
|
||||
GT68xx_Scan_Request * request,
|
||||
GT68xx_Scan_Action action,
|
||||
GT68xx_Scan_Parameters * params);
|
||||
|
||||
#endif /* not GT68XX_GT6801_H */
|
|
@ -0,0 +1,619 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2002 Sergey Vlasov <vsu@altlinux.ru>
|
||||
Copyright (C) 2002 Henning Meier-Geinitz <henning@meier-geinitz.de>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief Implementation of the gt6816 specific functions.
|
||||
*/
|
||||
|
||||
#include "gt68xx_gt6816.h"
|
||||
|
||||
SANE_Status
|
||||
gt6816_check_firmware (GT68xx_Device * dev, SANE_Bool * loaded)
|
||||
{
|
||||
SANE_Status status;
|
||||
GT68xx_Packet req;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0] = 0x70;
|
||||
req[1] = 0x01;
|
||||
|
||||
RIE (gt68xx_device_small_req (dev, req, req));
|
||||
|
||||
if (req[0] == 0x00 && req[1] == 0x70 && req[2] == 0xff)
|
||||
*loaded = SANE_TRUE;
|
||||
else
|
||||
*loaded = SANE_FALSE;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
#define MAX_DOWNLOAD_BLOCK_SIZE 64
|
||||
|
||||
SANE_Status
|
||||
gt6816_download_firmware (GT68xx_Device * dev,
|
||||
SANE_Byte * data, SANE_Word size)
|
||||
{
|
||||
DECLARE_FUNCTION_NAME ("gt6816_download_firmware") SANE_Status status;
|
||||
SANE_Byte download_buf[MAX_DOWNLOAD_BLOCK_SIZE];
|
||||
SANE_Byte check_buf[MAX_DOWNLOAD_BLOCK_SIZE];
|
||||
SANE_Byte *block;
|
||||
SANE_Word addr, bytes_left;
|
||||
GT68xx_Packet boot_req;
|
||||
SANE_Word block_size = MAX_DOWNLOAD_BLOCK_SIZE;
|
||||
|
||||
CHECK_DEV_ACTIVE (dev, function_name);
|
||||
|
||||
for (addr = 0; addr < size; addr += block_size)
|
||||
{
|
||||
bytes_left = size - addr;
|
||||
if (bytes_left > block_size)
|
||||
block = data + addr;
|
||||
else
|
||||
{
|
||||
memset (download_buf, 0, block_size);
|
||||
memcpy (download_buf, data + addr, bytes_left);
|
||||
block = download_buf;
|
||||
}
|
||||
RIE (gt68xx_device_memory_write (dev, addr, block_size, block));
|
||||
RIE (gt68xx_device_memory_read (dev, addr, block_size, check_buf));
|
||||
if (memcmp (block, check_buf, block_size) != 0)
|
||||
{
|
||||
XDBG ((3, "%s: mismatch at block 0x%0x\n", function_name, addr));
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
memset (boot_req, 0, sizeof (boot_req));
|
||||
boot_req[0] = 0x69;
|
||||
boot_req[1] = 0x01;
|
||||
boot_req[2] = LOBYTE (addr);
|
||||
boot_req[3] = HIBYTE (addr);
|
||||
RIE (gt68xx_device_req (dev, boot_req, boot_req));
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
gt6816_get_power_status (GT68xx_Device * dev, SANE_Bool * power_ok)
|
||||
{
|
||||
SANE_Status status;
|
||||
GT68xx_Packet req;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0] = 0x3f;
|
||||
req[1] = 0x01;
|
||||
|
||||
RIE (gt68xx_device_req (dev, req, req));
|
||||
|
||||
if (req[0] == 0x00 && req[1] == 0x3f && req[2] == 0x01)
|
||||
*power_ok = SANE_TRUE;
|
||||
else
|
||||
*power_ok = SANE_FALSE;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
gt6816_get_ta_status (GT68xx_Device * dev, SANE_Bool * ta_attached)
|
||||
{
|
||||
SANE_Status status;
|
||||
GT68xx_Packet req;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0] = 0x28;
|
||||
req[1] = 0x01;
|
||||
|
||||
RIE (gt68xx_device_req (dev, req, req));
|
||||
|
||||
if (req[0] == 0x00 && req[1] == 0x28 && (req[8] & 0x01) != 0
|
||||
&& !dev->model->is_cis)
|
||||
*ta_attached = SANE_TRUE;
|
||||
else
|
||||
*ta_attached = SANE_FALSE;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
gt6816_lamp_control (GT68xx_Device * dev, SANE_Bool fb_lamp,
|
||||
SANE_Bool ta_lamp)
|
||||
{
|
||||
GT68xx_Packet req;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0] = 0x25;
|
||||
req[1] = 0x01;
|
||||
req[2] = 0;
|
||||
if (fb_lamp)
|
||||
req[2] |= 0x01;
|
||||
if (ta_lamp)
|
||||
req[2] |= 0x02;
|
||||
|
||||
return gt68xx_device_req (dev, req, req);
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
gt6816_is_moving (GT68xx_Device * dev, SANE_Bool * moving)
|
||||
{
|
||||
SANE_Status status;
|
||||
GT68xx_Packet req;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0] = 0x17;
|
||||
req[1] = 0x01;
|
||||
|
||||
RIE (gt68xx_device_req (dev, req, req));
|
||||
|
||||
if (req[0] == 0x00 && req[1] == 0x17)
|
||||
{
|
||||
if (req[2] == 0 && (req[3] == 0 || req[3] == 2))
|
||||
*moving = SANE_FALSE;
|
||||
else
|
||||
*moving = SANE_TRUE;
|
||||
}
|
||||
else
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
gt6816_carriage_home (GT68xx_Device * dev)
|
||||
{
|
||||
GT68xx_Packet req;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0] = 0x24;
|
||||
req[1] = 0x01;
|
||||
|
||||
return gt68xx_device_req (dev, req, req);
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
gt6816_stop_scan (GT68xx_Device * dev)
|
||||
{
|
||||
GT68xx_Packet req;
|
||||
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0] = 0x41;
|
||||
req[1] = 0x01;
|
||||
|
||||
return gt68xx_device_small_req (dev, req, req);
|
||||
}
|
||||
|
||||
/* 3.0 mm of calibration */
|
||||
#define CALIBRATION_HEIGHT 3.0
|
||||
|
||||
SANE_Status
|
||||
gt6816_setup_scan (GT68xx_Device * dev,
|
||||
GT68xx_Scan_Request * request,
|
||||
GT68xx_Scan_Action action, GT68xx_Scan_Parameters * params)
|
||||
{
|
||||
DECLARE_FUNCTION_NAME ("gt6816_setup_scan") SANE_Status status;
|
||||
GT68xx_Model *model;
|
||||
SANE_Int xdpi, ydpi;
|
||||
SANE_Bool color;
|
||||
SANE_Int depth;
|
||||
SANE_Int pixel_x0, pixel_y0, pixel_xs, pixel_ys;
|
||||
SANE_Int pixel_align;
|
||||
|
||||
SANE_Int abs_x0, abs_y0, abs_xs, abs_ys, base_xdpi, base_ydpi;
|
||||
SANE_Int scan_xs, scan_ys, scan_bpl;
|
||||
SANE_Int bits_per_line;
|
||||
SANE_Byte color_mode_code;
|
||||
SANE_Bool line_mode;
|
||||
SANE_Int overscan_lines;
|
||||
SANE_Fixed x0, y0, xs, ys;
|
||||
SANE_Bool backtrack = SANE_FALSE;
|
||||
|
||||
XDBG ((5, "%s: enter (action=%s)\n", function_name,
|
||||
action == SA_CALIBRATE ? "calibrate" :
|
||||
action == SA_CALIBRATE_ONE_LINE ? "calibrate one line" :
|
||||
action == SA_SCAN ? "scan" : "calculate only"));
|
||||
|
||||
model = dev->model;
|
||||
|
||||
xdpi = request->xdpi;
|
||||
ydpi = request->ydpi;
|
||||
color = request->color;
|
||||
depth = request->depth;
|
||||
|
||||
base_xdpi = model->base_xdpi;
|
||||
base_ydpi = model->base_ydpi;
|
||||
|
||||
if (xdpi > model->base_xdpi)
|
||||
base_xdpi = model->optical_xdpi;
|
||||
|
||||
/* Special fixes */
|
||||
if (strcmp (model->name, "mustek-bearpaw-2400-ta-plus") == 0 && xdpi <= 50)
|
||||
base_xdpi = model->optical_xdpi;
|
||||
if (ydpi <= 100)
|
||||
{
|
||||
if ((strcmp (model->name, "mustek-bearpaw-2400-ta-plus") == 0 ||
|
||||
strcmp (model->name, "mustek-bearpaw-2400-ta") == 0) &&
|
||||
!request->use_ta && action == SA_SCAN)
|
||||
request->mbs = SANE_TRUE; /* 50/100 dpi need a mimimum y0 */
|
||||
}
|
||||
|
||||
if (!model->constant_ydpi)
|
||||
{
|
||||
if (ydpi > model->base_ydpi)
|
||||
base_ydpi = model->optical_ydpi;
|
||||
}
|
||||
|
||||
XDBG ((5, "%s: base_xdpi=%d, base_ydpi=%d\n", function_name,
|
||||
base_xdpi, base_ydpi));
|
||||
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case SA_CALIBRATE_ONE_LINE:
|
||||
{
|
||||
x0 = request->x0;
|
||||
if (request->use_ta)
|
||||
y0 = model->y_offset_calib_ta;
|
||||
else
|
||||
y0 = model->y_offset_calib;
|
||||
ys = SANE_FIX (1.0 * MM_PER_INCH / ydpi); /* one line */
|
||||
xs = request->xs;
|
||||
depth = 8;
|
||||
color = request->color;
|
||||
break;
|
||||
}
|
||||
case SA_CALIBRATE:
|
||||
{
|
||||
if (request->use_ta)
|
||||
{
|
||||
x0 = request->x0 + model->x_offset_ta;
|
||||
if (request->mbs)
|
||||
y0 = model->y_offset_calib_ta;
|
||||
else
|
||||
y0 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
x0 = request->x0 + model->x_offset;
|
||||
if (request->mbs)
|
||||
y0 = model->y_offset_calib;
|
||||
else
|
||||
y0 = 0;
|
||||
}
|
||||
ys = SANE_FIX (CALIBRATION_HEIGHT);
|
||||
xs = request->xs;
|
||||
color = request->color;
|
||||
break;
|
||||
}
|
||||
case SA_SCAN:
|
||||
{
|
||||
SANE_Fixed x_offset, y_offset;
|
||||
if (request->use_ta)
|
||||
{
|
||||
x_offset = model->x_offset_ta;
|
||||
if (request->mbs)
|
||||
y_offset = model->y_offset_ta;
|
||||
else
|
||||
y_offset = model->y_offset_ta - model->y_offset_calib_ta
|
||||
- SANE_FIX (CALIBRATION_HEIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
x_offset = model->x_offset;
|
||||
if (request->mbs)
|
||||
y_offset = model->y_offset;
|
||||
else
|
||||
y_offset = model->y_offset - model->y_offset_calib
|
||||
- SANE_FIX (CALIBRATION_HEIGHT);
|
||||
}
|
||||
x0 = request->x0 + x_offset;
|
||||
y0 = request->y0 + y_offset;
|
||||
ys = request->ys;
|
||||
xs = request->xs;
|
||||
|
||||
backtrack = SANE_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
XDBG ((5, "%s: invalid action=%d\n", function_name, (int) action));
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
pixel_x0 = SANE_UNFIX (x0) * xdpi / MM_PER_INCH + 0.5;
|
||||
pixel_y0 = SANE_UNFIX (y0) * ydpi / MM_PER_INCH + 0.5;
|
||||
pixel_ys = SANE_UNFIX (ys) * ydpi / MM_PER_INCH + 0.5;
|
||||
pixel_xs = SANE_UNFIX (xs) * xdpi / MM_PER_INCH + 0.5;
|
||||
|
||||
|
||||
XDBG ((5, "%s: xdpi=%d, ydpi=%d\n", function_name, xdpi, ydpi));
|
||||
XDBG ((5, "%s: color=%s, depth=%d\n", function_name,
|
||||
color ? "TRUE" : "FALSE", depth));
|
||||
XDBG ((5, "%s: pixel_x0=%d, pixel_y0=%d\n", function_name,
|
||||
pixel_x0, pixel_y0));
|
||||
XDBG ((5, "%s: pixel_xs=%d, pixel_ys=%d\n", function_name,
|
||||
pixel_xs, pixel_ys));
|
||||
XDBG ((5, "%s: backtrack=%d\n", function_name, backtrack));
|
||||
|
||||
|
||||
color_mode_code = 0x80; /* What does this mean ? */
|
||||
if (color)
|
||||
color_mode_code |= (1 << 2);
|
||||
else
|
||||
color_mode_code |= (1 << 1);
|
||||
|
||||
if (depth > 12)
|
||||
color_mode_code |= (1 << 5);
|
||||
else if (depth > 8)
|
||||
{
|
||||
color_mode_code &= 0x7f;
|
||||
color_mode_code |= (1 << 4);
|
||||
}
|
||||
|
||||
XDBG ((5, "%s: color_mode_code = 0x%02X\n", function_name,
|
||||
color_mode_code));
|
||||
|
||||
overscan_lines = 0;
|
||||
params->ld_shift_r = params->ld_shift_g = params->ld_shift_b = 0;
|
||||
params->ld_shift_double = 0;
|
||||
|
||||
if (action == SA_SCAN && color)
|
||||
{
|
||||
/* Line distance correction is required for color scans. */
|
||||
SANE_Int optical_ydpi = model->optical_ydpi;
|
||||
SANE_Int ld_shift_r = model->ld_shift_r;
|
||||
SANE_Int ld_shift_g = model->ld_shift_g;
|
||||
SANE_Int ld_shift_b = model->ld_shift_b;
|
||||
SANE_Int max_ld = MAX (MAX (ld_shift_r, ld_shift_g), ld_shift_b);
|
||||
|
||||
overscan_lines = max_ld * ydpi / optical_ydpi;
|
||||
params->ld_shift_r = ld_shift_r * ydpi / optical_ydpi;
|
||||
params->ld_shift_g = ld_shift_g * ydpi / optical_ydpi;
|
||||
params->ld_shift_b = ld_shift_b * ydpi / optical_ydpi;
|
||||
params->ld_shift_double = 0;
|
||||
XDBG ((5, "%s: overscan=%d, ld=%d/%d/%d\n", function_name,
|
||||
overscan_lines, params->ld_shift_r, params->ld_shift_g,
|
||||
params->ld_shift_b));
|
||||
}
|
||||
|
||||
if (action == SA_SCAN && xdpi >= model->optical_xdpi
|
||||
&& model->ld_shift_double > 0)
|
||||
{
|
||||
params->ld_shift_double =
|
||||
model->ld_shift_double * ydpi / model->optical_ydpi;
|
||||
if (color)
|
||||
overscan_lines += (params->ld_shift_double * 3);
|
||||
else
|
||||
overscan_lines += params->ld_shift_double;
|
||||
|
||||
XDBG ((5, "%s: overscan=%d, ld double=%d\n", function_name,
|
||||
overscan_lines, params->ld_shift_double));
|
||||
}
|
||||
|
||||
abs_x0 = pixel_x0 * base_xdpi / xdpi;
|
||||
abs_y0 = pixel_y0 * base_ydpi / ydpi;
|
||||
XDBG ((5, "%s: abs_x0=%d, abs_y0=%d\n", function_name, abs_x0, abs_y0));
|
||||
|
||||
params->double_column = abs_x0 & 1;
|
||||
|
||||
/* Calculate minimum number of pixels which span an integral multiple of 64
|
||||
* bytes. */
|
||||
pixel_align = 32; /* best case for depth = 16 */
|
||||
while ((depth * pixel_align) % (64 * 8) != 0)
|
||||
pixel_align *= 2;
|
||||
XDBG ((5, "%s: pixel_align=%d\n", function_name, pixel_align));
|
||||
|
||||
if (pixel_xs % pixel_align == 0)
|
||||
scan_xs = pixel_xs;
|
||||
else
|
||||
scan_xs = (pixel_xs / pixel_align + 1) * pixel_align;
|
||||
scan_ys = pixel_ys + overscan_lines;
|
||||
|
||||
abs_xs = scan_xs * base_xdpi / xdpi;
|
||||
if (action == SA_CALIBRATE_ONE_LINE)
|
||||
abs_ys = 2;
|
||||
else
|
||||
abs_ys = scan_ys * base_ydpi / ydpi;
|
||||
XDBG ((5, "%s: abs_xs=%d, abs_ys=%d\n", function_name, abs_xs, abs_ys));
|
||||
|
||||
if (model->is_cis)
|
||||
{
|
||||
line_mode = SANE_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
line_mode = SANE_FALSE;
|
||||
if (!color) /* ??? */
|
||||
{
|
||||
XDBG ((5, "%s: using line mode for monochrome scan\n",
|
||||
function_name));
|
||||
line_mode = SANE_TRUE;
|
||||
}
|
||||
else if (ydpi >= model->ydpi_force_line_mode)
|
||||
{
|
||||
XDBG ((5, "%s: forcing line mode for ydpi=%d\n", function_name,
|
||||
ydpi));
|
||||
line_mode = SANE_TRUE;
|
||||
}
|
||||
#if 1
|
||||
else if (ydpi == 600 && depth == 16) /* XXX */
|
||||
{
|
||||
XDBG ((5, "%s: forcing line mode for ydpi=%d, depth=%d\n",
|
||||
function_name, ydpi, depth));
|
||||
line_mode = SANE_TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
bits_per_line = depth * scan_xs;
|
||||
if (color && !line_mode)
|
||||
bits_per_line *= 3;
|
||||
if (bits_per_line % 8) /* impossible */
|
||||
{
|
||||
XDBG ((0, "%s: BUG: unaligned bits_per_line=%d\n", function_name,
|
||||
bits_per_line));
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
scan_bpl = bits_per_line / 8;
|
||||
|
||||
if (scan_bpl > 15600 && !line_mode) /* ??? */
|
||||
{
|
||||
XDBG ((5, "%s: scan_bpl=%d, trying line mode\n", function_name,
|
||||
scan_bpl));
|
||||
line_mode = SANE_TRUE;
|
||||
if (scan_bpl % 3)
|
||||
{
|
||||
XDBG ((0, "%s: BUG: monochrome scan in pixel mode?\n",
|
||||
function_name));
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
scan_bpl /= 3;
|
||||
}
|
||||
|
||||
if (scan_bpl % 64) /* impossible */
|
||||
{
|
||||
XDBG ((0, "%s: BUG: unaligned scan_bpl=%d\n", function_name, scan_bpl));
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
if (scan_bpl > 15600) /* ??? */
|
||||
{
|
||||
XDBG ((5, "%s: scan_bpl=%d, too large\n", function_name, scan_bpl));
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
/* really? */
|
||||
|
||||
if (color && line_mode)
|
||||
scan_ys *= 3;
|
||||
|
||||
XDBG ((5, "%s: scan_xs=%d, scan_ys=%d\n", function_name, scan_xs, scan_ys));
|
||||
|
||||
XDBG ((5, "%s: scan_bpl=%d\n", function_name, scan_bpl));
|
||||
|
||||
if (!request->calculate)
|
||||
{
|
||||
GT68xx_Packet req;
|
||||
SANE_Byte motor_mode_1, motor_mode_2;
|
||||
|
||||
motor_mode_1 = (request->mbs ? 0 : 1) << 1;
|
||||
motor_mode_1 |= (request->mds ? 0 : 1) << 2;
|
||||
motor_mode_1 |= (request->mas ? 0 : 1) << 0;
|
||||
|
||||
motor_mode_1 |= (backtrack ? 1 : 0) << 3;
|
||||
|
||||
motor_mode_2 = (request->lamp ? 0 : 1) << 0;
|
||||
motor_mode_2 |= (line_mode ? 0 : 1) << 2;
|
||||
|
||||
if (action != SA_SCAN)
|
||||
motor_mode_2 |= 1 << 3;
|
||||
|
||||
XDBG ((5, "%s: motor_mode_1 = 0x%02X, motor_mode_2 = 0x%02X\n",
|
||||
function_name, motor_mode_1, motor_mode_2));
|
||||
|
||||
/* Fill in the setup command */
|
||||
memset (req, 0, sizeof (req));
|
||||
req[0x00] = 0x20;
|
||||
req[0x01] = 0x01;
|
||||
req[0x02] = LOBYTE (abs_y0);
|
||||
req[0x03] = HIBYTE (abs_y0);
|
||||
req[0x04] = LOBYTE (abs_ys);
|
||||
req[0x05] = HIBYTE (abs_ys);
|
||||
req[0x06] = LOBYTE (abs_x0);
|
||||
req[0x07] = HIBYTE (abs_x0);
|
||||
req[0x08] = LOBYTE (abs_xs);
|
||||
req[0x09] = HIBYTE (abs_xs);
|
||||
req[0x0a] = color_mode_code;
|
||||
req[0x0b] = 0x20; /* 0x20 CCD; 0x60 CIS, I don't see any difference */
|
||||
req[0x0c] = LOBYTE (xdpi);
|
||||
req[0x0d] = HIBYTE (xdpi);
|
||||
req[0x0e] = 0x12; /* 0x12 ??? */
|
||||
req[0x0f] = 0x00;
|
||||
req[0x10] = LOBYTE (scan_bpl);
|
||||
req[0x11] = HIBYTE (scan_bpl);
|
||||
req[0x12] = LOBYTE (scan_ys);
|
||||
req[0x13] = HIBYTE (scan_ys);
|
||||
req[0x14] = motor_mode_1;
|
||||
req[0x15] = motor_mode_2;
|
||||
req[0x16] = LOBYTE (ydpi);
|
||||
req[0x17] = HIBYTE (ydpi);
|
||||
if (backtrack)
|
||||
{
|
||||
if (model->is_cis)
|
||||
req[0x18] = 0x20;
|
||||
else
|
||||
req[0x18] = 0x3f;
|
||||
}
|
||||
else
|
||||
req[0x18] = 0x00;
|
||||
status = gt68xx_device_req (dev, req, req);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
XDBG ((3, "%s: setup request failed: %s\n", function_name,
|
||||
sane_strstatus (status)));
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill in calculated values */
|
||||
params->xdpi = xdpi;
|
||||
params->ydpi = ydpi;
|
||||
params->depth = depth;
|
||||
params->color = color;
|
||||
params->pixel_xs = pixel_xs;
|
||||
params->pixel_ys = pixel_ys;
|
||||
params->scan_xs = scan_xs;
|
||||
params->scan_ys = scan_ys;
|
||||
params->scan_bpl = scan_bpl;
|
||||
params->line_mode = line_mode;
|
||||
params->overscan_lines = overscan_lines;
|
||||
|
||||
XDBG ((6, "%s: leave: ok\n", function_name));
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
|
|
@ -0,0 +1,76 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2002 Sergey Vlasov <vsu@altlinux.ru>
|
||||
|
||||
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 GT68XX_GT6816_H
|
||||
#define GT68XX_GT6816_H
|
||||
|
||||
static SANE_Status
|
||||
gt6816_check_firmware (GT68xx_Device * dev, SANE_Bool * loaded);
|
||||
|
||||
static SANE_Status
|
||||
gt6816_download_firmware (GT68xx_Device * dev,
|
||||
SANE_Byte * data, SANE_Word size);
|
||||
|
||||
static SANE_Status
|
||||
gt6816_get_power_status (GT68xx_Device * dev, SANE_Bool * power_ok);
|
||||
|
||||
static SANE_Status
|
||||
gt6816_get_ta_status (GT68xx_Device * dev, SANE_Bool * ta_attached);
|
||||
|
||||
static SANE_Status
|
||||
gt6816_lamp_control (GT68xx_Device * dev, SANE_Bool fb_lamp,
|
||||
SANE_Bool ta_lamp);
|
||||
|
||||
static SANE_Status gt6816_is_moving (GT68xx_Device * dev, SANE_Bool * moving);
|
||||
|
||||
static SANE_Status gt6816_carriage_home (GT68xx_Device * dev);
|
||||
|
||||
static SANE_Status gt6816_stop_scan (GT68xx_Device * dev);
|
||||
|
||||
static SANE_Status
|
||||
gt6816_setup_scan (GT68xx_Device * dev,
|
||||
GT68xx_Scan_Request * request,
|
||||
GT68xx_Scan_Action action,
|
||||
GT68xx_Scan_Parameters * params);
|
||||
|
||||
#endif /* not GT68XX_GT6816_H */
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,328 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2002 Sergey Vlasov <vsu@altlinux.ru>
|
||||
Copyright (C) 2002 Henning Meier-Geinitz <henning@meier-geinitz.de>
|
||||
|
||||
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 GT68XX_HIGH_H
|
||||
#define GT68XX_HIGH_H
|
||||
|
||||
#include "gt68xx_mid.h"
|
||||
|
||||
typedef struct GT68xx_Calibrator GT68xx_Calibrator;
|
||||
typedef struct GT68xx_Scanner GT68xx_Scanner;
|
||||
|
||||
/** Calibration data for one channel.
|
||||
*/
|
||||
struct GT68xx_Calibrator
|
||||
{
|
||||
unsigned int *k_white; /**< White point vector */
|
||||
unsigned int *k_black; /**< Black point vector */
|
||||
|
||||
double *white_line; /**< White average */
|
||||
double *black_line; /**< Black average */
|
||||
|
||||
SANE_Int width; /**< Image width */
|
||||
SANE_Int white_level; /**< Desired white level */
|
||||
|
||||
SANE_Int white_count; /**< Number of white lines scanned */
|
||||
SANE_Int black_count; /**< Number of black lines scanned */
|
||||
|
||||
#ifdef TUNE_CALIBRATOR
|
||||
SANE_Int min_clip_count; /**< Count of too low values */
|
||||
SANE_Int max_clip_count; /**< Count of too high values */
|
||||
#endif /* TUNE_CALIBRATOR */
|
||||
};
|
||||
|
||||
/** Create a new calibrator for one (color or mono) channel.
|
||||
*
|
||||
* @param width Image width in pixels.
|
||||
* @param white_level Desired white level (65535 max).
|
||||
* @param cal_return Returned pointer to the created calibrator object.
|
||||
*
|
||||
* @return
|
||||
* - SANE_STATUS_GOOD - the calibrator object was created.
|
||||
* - SANE_STATUS_INVAL - invalid parameters.
|
||||
* - SANE_STATUS_NO_MEM - not enough memory to create the object.
|
||||
*/
|
||||
static SANE_Status
|
||||
gt68xx_calibrator_new (SANE_Int width,
|
||||
SANE_Int white_level, GT68xx_Calibrator ** cal_return);
|
||||
|
||||
/** Destroy the channel calibrator object.
|
||||
*
|
||||
* @param cal Calibrator object.
|
||||
*/
|
||||
static SANE_Status gt68xx_calibrator_free (GT68xx_Calibrator * cal);
|
||||
|
||||
/** Add a white calibration line to the calibrator.
|
||||
*
|
||||
* This function should be called after scanning each white calibration line.
|
||||
* The line width must be equal to the value passed to gt68xx_calibrator_new().
|
||||
*
|
||||
* @param cal Calibrator object.
|
||||
* @param line Pointer to the line data.
|
||||
*
|
||||
* @return
|
||||
* - #SANE_STATUS_GOOD - the line data was processed successfully.
|
||||
*/
|
||||
static SANE_Status
|
||||
gt68xx_calibrator_add_white_line (GT68xx_Calibrator * cal,
|
||||
unsigned int *line);
|
||||
|
||||
/** Calculate the white point for the calibrator.
|
||||
*
|
||||
* This function should be called when all white calibration lines have been
|
||||
* scanned. After doing this, gt68xx_calibrator_add_white_line() should not be
|
||||
* called again for this calibrator.
|
||||
*
|
||||
* @param cal Calibrator object.
|
||||
* @param factor White point correction factor.
|
||||
*
|
||||
* @return
|
||||
* - #SANE_STATUS_GOOD - the white point was calculated successfully.
|
||||
*/
|
||||
static SANE_Status
|
||||
gt68xx_calibrator_eval_white (GT68xx_Calibrator * cal, double factor);
|
||||
|
||||
/** Add a black calibration line to the calibrator.
|
||||
*
|
||||
* This function should be called after scanning each black calibration line.
|
||||
* The line width must be equal to the value passed to gt68xx_calibrator_new().
|
||||
*
|
||||
* @param cal Calibrator object.
|
||||
* @param line Pointer to the line data.
|
||||
*
|
||||
* @return
|
||||
* - #SANE_STATUS_GOOD - the line data was processed successfully.
|
||||
*/
|
||||
static SANE_Status
|
||||
gt68xx_calibrator_add_black_line (GT68xx_Calibrator * cal,
|
||||
unsigned int *line);
|
||||
|
||||
/** Calculate the black point for the calibrator.
|
||||
*
|
||||
* This function should be called when all black calibration lines have been
|
||||
* scanned. After doing this, gt68xx_calibrator_add_black_line() should not be
|
||||
* called again for this calibrator.
|
||||
*
|
||||
* @param cal Calibrator object.
|
||||
* @param factor Black point correction factor.
|
||||
*
|
||||
* @return
|
||||
* - #SANE_STATUS_GOOD - the white point was calculated successfully.
|
||||
*/
|
||||
static SANE_Status
|
||||
gt68xx_calibrator_eval_black (GT68xx_Calibrator * cal, double factor);
|
||||
|
||||
/** Finish the calibrator setup and prepare for real scanning.
|
||||
*
|
||||
* This function must be called after gt68xx_calibrator_eval_white() and
|
||||
* gt68xx_calibrator_eval_black().
|
||||
*
|
||||
* @param cal Calibrator object.
|
||||
*
|
||||
* @return
|
||||
* - #SANE_STATUS_GOOD - the calibrator setup completed successfully.
|
||||
*/
|
||||
static SANE_Status gt68xx_calibrator_finish_setup (GT68xx_Calibrator * cal);
|
||||
|
||||
/** Process the image line through the calibrator.
|
||||
*
|
||||
* This function must be called only after gt68xx_calibrator_finish_setup().
|
||||
* The image line is modified in place.
|
||||
*
|
||||
* @param cal Calibrator object.
|
||||
* @param line Pointer to the image line data.
|
||||
*
|
||||
* @return
|
||||
* - #SANE_STATUS_GOOD - the image line was processed successfully.
|
||||
*/
|
||||
static SANE_Status
|
||||
gt68xx_calibrator_process_line (GT68xx_Calibrator * cal, unsigned int *line);
|
||||
|
||||
/** List of SANE options
|
||||
*/
|
||||
enum GT68xx_Option
|
||||
{
|
||||
OPT_NUM_OPTS = 0,
|
||||
|
||||
OPT_MODE_GROUP,
|
||||
OPT_MODE,
|
||||
OPT_SOURCE,
|
||||
OPT_PREVIEW,
|
||||
OPT_BIT_DEPTH,
|
||||
OPT_RESOLUTION,
|
||||
OPT_LAMP_ON,
|
||||
OPT_AUTO_WARMUP,
|
||||
|
||||
OPT_DEBUG_GROUP,
|
||||
OPT_FULL_SCAN,
|
||||
OPT_AUTO_GAIN,
|
||||
OPT_AUTO_GAIN_ONCE,
|
||||
OPT_QUALITY_CAL,
|
||||
|
||||
OPT_ENHANCEMENT_GROUP,
|
||||
OPT_THRESHOLD,
|
||||
OPT_SCAN_EXPOS_TIME_R,
|
||||
OPT_SCAN_EXPOS_TIME_G,
|
||||
OPT_SCAN_EXPOS_TIME_B,
|
||||
OPT_OFFSET_R,
|
||||
OPT_OFFSET_G,
|
||||
OPT_OFFSET_B,
|
||||
OPT_GAIN_R,
|
||||
OPT_GAIN_G,
|
||||
OPT_GAIN_B,
|
||||
|
||||
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 */
|
||||
|
||||
/* must come last: */
|
||||
NUM_OPTIONS
|
||||
};
|
||||
|
||||
typedef union
|
||||
{
|
||||
SANE_Word w;
|
||||
SANE_Word *wa; /* word array */
|
||||
SANE_String s;
|
||||
}
|
||||
Option_Value;
|
||||
|
||||
/** Scanner object.
|
||||
*/
|
||||
struct GT68xx_Scanner
|
||||
{
|
||||
struct GT68xx_Scanner *next; /**< Next scanner in list */
|
||||
GT68xx_Device *dev; /**< Low-level device object */
|
||||
|
||||
GT68xx_Line_Reader *reader; /**< Line reader object */
|
||||
|
||||
GT68xx_Calibrator *cal_gray; /**< Calibrator for grayscale data */
|
||||
GT68xx_Calibrator *cal_r; /**< Calibrator for the red channel */
|
||||
GT68xx_Calibrator *cal_g; /**< Calibrator for the green channel */
|
||||
GT68xx_Calibrator *cal_b; /**< Calibrator for the blue channel */
|
||||
|
||||
/* SANE data */
|
||||
SANE_Bool scanning; /**< We are currently scanning */
|
||||
SANE_Option_Descriptor opt[NUM_OPTIONS]; /**< Option descriptors */
|
||||
Option_Value val[NUM_OPTIONS]; /**< Option values */
|
||||
SANE_Parameters params; /**< SANE Parameters */
|
||||
SANE_Int line; /**< Current line */
|
||||
SANE_Int total_bytes; /**< Bytes already transmitted */
|
||||
SANE_Int byte_count; /**< Bytes transmitted in this line */
|
||||
SANE_Bool calib; /**< Apply calibration data */
|
||||
SANE_Bool auto_afe; /**< Use automatic gain/offset */
|
||||
SANE_Bool first_scan; /**< Is this the first scan? */
|
||||
struct timeval lamp_on_time; /**< Time when the lamp was turned on */
|
||||
struct timeval start_time; /**< Time when the scan was started */
|
||||
SANE_Int bpp_list[5]; /**< */
|
||||
};
|
||||
|
||||
|
||||
/** Create a new scanner object.
|
||||
*
|
||||
* @param dev Low-level device object.
|
||||
* @param scanner_return Returned pointer to the created scanner object.
|
||||
*/
|
||||
static SANE_Status
|
||||
gt68xx_scanner_new (GT68xx_Device * dev, GT68xx_Scanner ** scanner_return);
|
||||
|
||||
/** Destroy the scanner object.
|
||||
*
|
||||
* The low-level device object is not destroyed.
|
||||
*
|
||||
* @param scanner Scanner object.
|
||||
*/
|
||||
static SANE_Status gt68xx_scanner_free (GT68xx_Scanner * scanner);
|
||||
|
||||
/** Calibrate the scanner before the main scan.
|
||||
*
|
||||
* @param scanner Scanner object.
|
||||
* @param request Scan request data.
|
||||
* @param use_autogain Enable automatic offset/gain control
|
||||
*/
|
||||
static SANE_Status
|
||||
gt68xx_scanner_calibrate (GT68xx_Scanner * scanner,
|
||||
GT68xx_Scan_Request * request);
|
||||
|
||||
/** Start scanning the image.
|
||||
*
|
||||
* This function does not perform calibration - it needs to be performed before
|
||||
* by calling gt68xx_scanner_calibrate().
|
||||
*
|
||||
* @param scanner Scanner object.
|
||||
* @param request Scan request data.
|
||||
* @param params Returned scan parameters (calculated from the request).
|
||||
*/
|
||||
static SANE_Status
|
||||
gt68xx_scanner_start_scan (GT68xx_Scanner * scanner,
|
||||
GT68xx_Scan_Request * request,
|
||||
GT68xx_Scan_Parameters * params);
|
||||
|
||||
/** Read one image line from the scanner.
|
||||
*
|
||||
* This function can be called only during the scan - after calling
|
||||
* gt68xx_scanner_start_scan() and before calling gt68xx_scanner_stop_scan().
|
||||
*
|
||||
* @param scanner Scanner object.
|
||||
* @param buffer_pointers Array of pointers to the image lines.
|
||||
*/
|
||||
static SANE_Status
|
||||
gt68xx_scanner_read_line (GT68xx_Scanner * scanner,
|
||||
unsigned int **buffer_pointers);
|
||||
|
||||
/** Stop scanning the image.
|
||||
*
|
||||
* This function must be called to finish the scan started by
|
||||
* gt68xx_scanner_start_scan(). It may be called before all lines are read to
|
||||
* cancel the scan prematurely.
|
||||
*
|
||||
* @param scanner Scanner object.
|
||||
*/
|
||||
static SANE_Status gt68xx_scanner_stop_scan (GT68xx_Scanner * scanner);
|
||||
|
||||
#endif /* not GT68XX_HIGH_H */
|
||||
|
||||
/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
|
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,154 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2002 Sergey Vlasov <vsu@altlinux.ru>
|
||||
|
||||
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 GT68XX_MID_H
|
||||
#define GT68XX_MID_H
|
||||
|
||||
/** @file
|
||||
* @brief Image data unpacking.
|
||||
*/
|
||||
|
||||
#include "gt68xx_low.h"
|
||||
#include "../include/sane/sane.h"
|
||||
|
||||
typedef struct GT68xx_Delay_Buffer GT68xx_Delay_Buffer;
|
||||
typedef struct GT68xx_Line_Reader GT68xx_Line_Reader;
|
||||
|
||||
struct GT68xx_Delay_Buffer
|
||||
{
|
||||
SANE_Int line_count;
|
||||
SANE_Int read_index;
|
||||
SANE_Int write_index;
|
||||
unsigned int **lines;
|
||||
SANE_Byte *mem_block;
|
||||
};
|
||||
|
||||
/**
|
||||
* Object for reading image data line by line, with line distance correction.
|
||||
*
|
||||
* This object handles reading the image data from the scanner line by line and
|
||||
* converting it to internal format. Internally each image sample is
|
||||
* represented as <code>unsigned int</code> value, scaled to 16-bit range
|
||||
* (0-65535). For color images the data for each primary color is stored as
|
||||
* separate lines.
|
||||
*/
|
||||
struct GT68xx_Line_Reader
|
||||
{
|
||||
GT68xx_Device *dev; /**< Low-level interface object */
|
||||
GT68xx_Scan_Parameters params; /**< Scan parameters */
|
||||
|
||||
#if 0
|
||||
/** Number of bytes in the returned scanlines */
|
||||
SANE_Int bytes_per_line;
|
||||
|
||||
/** Number of bytes per pixel in the returned scanlines */
|
||||
SANE_Int bytes_per_pixel;
|
||||
#endif
|
||||
|
||||
/** Number of pixels in the returned scanlines */
|
||||
SANE_Int pixels_per_line;
|
||||
|
||||
SANE_Byte *pixel_buffer;
|
||||
|
||||
GT68xx_Delay_Buffer r_delay;
|
||||
GT68xx_Delay_Buffer g_delay;
|
||||
GT68xx_Delay_Buffer b_delay;
|
||||
SANE_Bool delays_initialized;
|
||||
|
||||
SANE_Status (*read) (GT68xx_Line_Reader * reader,
|
||||
unsigned int **buffer_pointers_return);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new GT68xx_Line_Reader object.
|
||||
*
|
||||
* @param dev The low-level scanner interface object.
|
||||
* @param params Scan parameters prepared by gt68xx_device_setup_scan().
|
||||
* @param final_scan SANE_TRUE for the final scan, SANE_FALSE for
|
||||
* calibration scans.
|
||||
* @param reader_return Location for the returned object.
|
||||
*
|
||||
* @return
|
||||
* - SANE_STATUS_GOOD - on success
|
||||
* - SANE_STATUS_NO_MEM - cannot allocate memory for object or buffers
|
||||
* - other error values - failure of some internal functions
|
||||
*/
|
||||
static SANE_Status
|
||||
gt68xx_line_reader_new (GT68xx_Device * dev,
|
||||
GT68xx_Scan_Parameters * params,
|
||||
SANE_Bool final_scan,
|
||||
GT68xx_Line_Reader ** reader_return);
|
||||
|
||||
/**
|
||||
* Destroy the GT68xx_Line_Reader object.
|
||||
*
|
||||
* @param reader The GT68xx_Line_Reader object to destroy.
|
||||
*/
|
||||
static SANE_Status gt68xx_line_reader_free (GT68xx_Line_Reader * reader);
|
||||
|
||||
/**
|
||||
* Read a scanline from the GT68xx_Line_Reader object.
|
||||
*
|
||||
* @param reader The GT68xx_Line_Reader object.
|
||||
* @param buffer_pointers_return Array of pointers to image lines (1 or 3
|
||||
* elements)
|
||||
*
|
||||
* This function reads a full scanline from the device, unpacks it to internal
|
||||
* buffers and returns pointer to these buffers in @a
|
||||
* buffer_pointers_return[i]. For monochrome scan, only @a
|
||||
* buffer_pointers_return[0] is filled; for color scan, elements 0, 1, 2 are
|
||||
* filled with pointers to red, green, and blue data. The returned pointers
|
||||
* are valid until the next call to gt68xx_line_reader_read(), or until @a
|
||||
* reader is destroyed.
|
||||
*
|
||||
* @return
|
||||
* - SANE_STATUS_GOOD - read completed successfully
|
||||
* - other error value - an error occured
|
||||
*/
|
||||
static SANE_Status
|
||||
gt68xx_line_reader_read (GT68xx_Line_Reader * reader,
|
||||
unsigned int **buffer_pointers_return);
|
||||
|
||||
#endif /* not GT68XX_MID_H */
|
||||
|
||||
/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
|
|
@ -0,0 +1,665 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2002 Sergey Vlasov <vsu@altlinux.ru>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief Shared memory channel implementation.
|
||||
*/
|
||||
|
||||
#include "gt68xx_shm_channel.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
/** Shared memory channel.
|
||||
*
|
||||
*/
|
||||
struct Shm_Channel
|
||||
{
|
||||
SANE_Int buf_size; /**< Size of each buffer */
|
||||
SANE_Int buf_count; /**< Number of buffers */
|
||||
void *shm_area; /**< Address of shared memory area */
|
||||
SANE_Byte **buffers; /**< Array of pointers to buffers */
|
||||
SANE_Int *buffer_bytes; /**< Array of buffer byte counts */
|
||||
int writer_put_pipe[2]; /**< Notification pipe from writer */
|
||||
int reader_put_pipe[2]; /**< Notification pipe from reader */
|
||||
};
|
||||
|
||||
/** Dummy union to find out the needed alignment */
|
||||
union Shm_Channel_Align
|
||||
{
|
||||
int i;
|
||||
long l;
|
||||
void *ptr;
|
||||
void (*func_ptr) (void);
|
||||
double d;
|
||||
};
|
||||
|
||||
/** Check if shm_channel is valid */
|
||||
#define SHM_CHANNEL_CHECK(shm_channel, func_name) \
|
||||
do { \
|
||||
if ((shm_channel) == NULL) \
|
||||
{ \
|
||||
DBG (3, "%s: BUG: shm_channel==NULL\n", (func_name)); \
|
||||
return SANE_STATUS_INVAL; \
|
||||
} \
|
||||
} while (SANE_FALSE)
|
||||
|
||||
/** Alignment for shared memory contents */
|
||||
#define SHM_CHANNEL_ALIGNMENT (sizeof (union Shm_Channel_Align))
|
||||
|
||||
/** Align the given size up to a multiple of the given alignment */
|
||||
#define SHM_CHANNEL_ROUND_UP(size, align) \
|
||||
( ((size) % (align)) ? ((size)/(align) + 1)*(align) : (size) )
|
||||
|
||||
/** Align the size using SHM_CHANNEL_ALIGNMENT */
|
||||
#define SHM_CHANNEL_ALIGN(size) \
|
||||
SHM_CHANNEL_ROUND_UP((size_t) (size), SHM_CHANNEL_ALIGNMENT)
|
||||
|
||||
/** Close a file descriptor if it is currently open.
|
||||
*
|
||||
* This function checks if the file descriptor is not -1, and sets it to -1
|
||||
* after close (so that it will not be closed twice).
|
||||
*
|
||||
* @param fd_var Pointer to a variable holding the file descriptor.
|
||||
*/
|
||||
static void
|
||||
shm_channel_fd_safe_close (int *fd_var)
|
||||
{
|
||||
if (*fd_var != -1)
|
||||
{
|
||||
close (*fd_var);
|
||||
*fd_var = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static SANE_Status
|
||||
shm_channel_fd_set_close_on_exec (int fd)
|
||||
{
|
||||
long value;
|
||||
|
||||
value = fcntl (fd, F_GETFD, 0L);
|
||||
if (value == -1)
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
if (fcntl (fd, F_SETFD, value | FD_CLOEXEC) == -1)
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static SANE_Status
|
||||
shm_channel_fd_set_non_blocking (int fd, SANE_Bool non_blocking)
|
||||
{
|
||||
long value;
|
||||
|
||||
value = fcntl (fd, F_GETFL, 0L);
|
||||
if (value == -1)
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
|
||||
if (non_blocking)
|
||||
value |= O_NONBLOCK;
|
||||
else
|
||||
value &= ~O_NONBLOCK;
|
||||
|
||||
if (fcntl (fd, F_SETFL, value) == -1)
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Create a new shared memory channel.
|
||||
*
|
||||
* This function should be called before the fork to set up the shared memory.
|
||||
*
|
||||
* @param buf_size Size of each shared memory buffer in bytes.
|
||||
* @param buf_count Number of shared memory buffers (up to 255).
|
||||
* @param shm_channel_return Returned shared memory channel object.
|
||||
*/
|
||||
SANE_Status
|
||||
shm_channel_new (SANE_Int buf_size,
|
||||
SANE_Int buf_count, Shm_Channel ** shm_channel_return)
|
||||
{
|
||||
Shm_Channel *shm_channel;
|
||||
void *shm_area;
|
||||
SANE_Byte *shm_data;
|
||||
int shm_buffer_bytes_size, shm_buffer_size;
|
||||
int shm_size;
|
||||
int shm_id;
|
||||
int i;
|
||||
|
||||
if (buf_size <= 0)
|
||||
{
|
||||
DBG (3, "shm_channel_new: invalid buf_size=%d\n", buf_size);
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
if (buf_count <= 0 || buf_count > 255)
|
||||
{
|
||||
DBG (3, "shm_channel_new: invalid buf_count=%d\n", buf_count);
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
if (!shm_channel_return)
|
||||
{
|
||||
DBG (3, "shm_channel_new: BUG: shm_channel_return==NULL\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
*shm_channel_return = NULL;
|
||||
|
||||
shm_channel = (Shm_Channel *) malloc (sizeof (Shm_Channel));
|
||||
if (!shm_channel)
|
||||
{
|
||||
DBG (3, "shm_channel_new: no memory for Shm_Channel\n");
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
shm_channel->buf_size = buf_size;
|
||||
shm_channel->buf_count = buf_count;
|
||||
shm_channel->shm_area = NULL;
|
||||
shm_channel->buffers = NULL;
|
||||
shm_channel->buffer_bytes = NULL;
|
||||
shm_channel->writer_put_pipe[0] = shm_channel->writer_put_pipe[1] = -1;
|
||||
shm_channel->reader_put_pipe[0] = shm_channel->reader_put_pipe[1] = -1;
|
||||
|
||||
shm_channel->buffers =
|
||||
(SANE_Byte **) malloc (sizeof (SANE_Byte *) * buf_count);
|
||||
if (!shm_channel->buffers)
|
||||
{
|
||||
DBG (3, "shm_channel_new: no memory for buffer pointers\n");
|
||||
shm_channel_free (shm_channel);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
if (pipe (shm_channel->writer_put_pipe) == -1)
|
||||
{
|
||||
DBG (3, "shm_channel_new: cannot create writer put pipe: %s\n",
|
||||
strerror (errno));
|
||||
shm_channel_free (shm_channel);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
if (pipe (shm_channel->reader_put_pipe) == -1)
|
||||
{
|
||||
DBG (3, "shm_channel_new: cannot create reader put pipe: %s\n",
|
||||
strerror (errno));
|
||||
shm_channel_free (shm_channel);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
shm_channel_fd_set_close_on_exec (shm_channel->reader_put_pipe[0]);
|
||||
shm_channel_fd_set_close_on_exec (shm_channel->reader_put_pipe[1]);
|
||||
shm_channel_fd_set_close_on_exec (shm_channel->writer_put_pipe[0]);
|
||||
shm_channel_fd_set_close_on_exec (shm_channel->writer_put_pipe[1]);
|
||||
|
||||
shm_buffer_bytes_size = SHM_CHANNEL_ALIGN (sizeof (SANE_Int) * buf_count);
|
||||
shm_buffer_size = SHM_CHANNEL_ALIGN (buf_size);
|
||||
shm_size = shm_buffer_bytes_size + buf_count * shm_buffer_size;
|
||||
|
||||
shm_id = shmget (IPC_PRIVATE, shm_size, IPC_CREAT | SHM_R | SHM_W);
|
||||
if (shm_id == -1)
|
||||
{
|
||||
DBG (3, "shm_channel_new: cannot create shared memory segment: %s\n",
|
||||
strerror (errno));
|
||||
shm_channel_free (shm_channel);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
shm_area = shmat (shm_id, NULL, 0);
|
||||
if (shm_area == (void *) -1)
|
||||
{
|
||||
DBG (3, "shm_channel_new: cannot attach to shared memory segment: %s\n",
|
||||
strerror (errno));
|
||||
shmctl (shm_id, IPC_RMID, NULL);
|
||||
shm_channel_free (shm_channel);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
if (shmctl (shm_id, IPC_RMID, NULL) == -1)
|
||||
{
|
||||
DBG (3, "shm_channel_new: cannot remove shared memory segment id: %s\n",
|
||||
strerror (errno));
|
||||
shmdt (shm_area);
|
||||
shmctl (shm_id, IPC_RMID, NULL);
|
||||
shm_channel_free (shm_channel);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
shm_channel->shm_area = shm_area;
|
||||
|
||||
shm_channel->buffer_bytes = (SANE_Int *) shm_area;
|
||||
shm_data = ((SANE_Byte *) shm_area) + shm_buffer_bytes_size;
|
||||
for (i = 0; i < shm_channel->buf_count; ++i)
|
||||
{
|
||||
shm_channel->buffers[i] = shm_data;
|
||||
shm_data += shm_buffer_size;
|
||||
}
|
||||
|
||||
*shm_channel_return = shm_channel;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/** Close the shared memory channel and release associated resources.
|
||||
*
|
||||
* @param shm_channel Shared memory channel object.
|
||||
*/
|
||||
SANE_Status
|
||||
shm_channel_free (Shm_Channel * shm_channel)
|
||||
{
|
||||
SHM_CHANNEL_CHECK (shm_channel, "shm_channel_free");
|
||||
|
||||
if (shm_channel->shm_area)
|
||||
{
|
||||
shmdt (shm_channel->shm_area);
|
||||
shm_channel->shm_area = NULL;
|
||||
}
|
||||
|
||||
if (shm_channel->buffers)
|
||||
{
|
||||
free (shm_channel->buffers);
|
||||
shm_channel->buffers = NULL;
|
||||
}
|
||||
|
||||
shm_channel_fd_safe_close (&shm_channel->reader_put_pipe[0]);
|
||||
shm_channel_fd_safe_close (&shm_channel->reader_put_pipe[1]);
|
||||
shm_channel_fd_safe_close (&shm_channel->writer_put_pipe[0]);
|
||||
shm_channel_fd_safe_close (&shm_channel->writer_put_pipe[1]);
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/** Initialize the shared memory channel in the writer process.
|
||||
*
|
||||
* This function should be called after the fork in the process which will
|
||||
* write data to the channel.
|
||||
*
|
||||
* @param shm_channel Shared memory channel object.
|
||||
*/
|
||||
SANE_Status
|
||||
shm_channel_writer_init (Shm_Channel * shm_channel)
|
||||
{
|
||||
SHM_CHANNEL_CHECK (shm_channel, "shm_channel_writer_init");
|
||||
|
||||
shm_channel_fd_safe_close (&shm_channel->writer_put_pipe[0]);
|
||||
shm_channel_fd_safe_close (&shm_channel->reader_put_pipe[1]);
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/** Get a free shared memory buffer for writing.
|
||||
*
|
||||
* This function may block waiting for a free buffer (if the reader process
|
||||
* does not process the data fast enough).
|
||||
*
|
||||
* After successfull call to this function the writer process should fill the
|
||||
* buffer with the data and pass the buffer identifier from @a buffer_id_return
|
||||
* to shm_channel_writer_put_buffer() to give the buffer to the reader process.
|
||||
*
|
||||
* @param shm_channel Shared memory channel object.
|
||||
* @param buffer_id_return Returned buffer identifier.
|
||||
* @param buffer_addr_return Returned buffer address.
|
||||
*
|
||||
* @return
|
||||
* - SANE_STATUS_GOOD - a free buffer was available (or became available after
|
||||
* waiting for it); @a buffer_id_return and @a buffer_addr_return are filled
|
||||
* with valid values.
|
||||
* - SANE_STATUS_EOF - the reader process has closed its half of the channel.
|
||||
* - SANE_STATUS_IO_ERROR - an I/O error occured.
|
||||
*/
|
||||
SANE_Status
|
||||
shm_channel_writer_get_buffer (Shm_Channel * shm_channel,
|
||||
SANE_Int * buffer_id_return,
|
||||
SANE_Byte ** buffer_addr_return)
|
||||
{
|
||||
SANE_Byte buf_index;
|
||||
int bytes_read;
|
||||
|
||||
SHM_CHANNEL_CHECK (shm_channel, "shm_channel_writer_get_buffer");
|
||||
|
||||
do
|
||||
bytes_read = read (shm_channel->reader_put_pipe[0], &buf_index, 1);
|
||||
while (bytes_read == -1 && errno == EINTR);
|
||||
|
||||
if (bytes_read == 1)
|
||||
{
|
||||
SANE_Int index = buf_index;
|
||||
if (index < shm_channel->buf_count)
|
||||
{
|
||||
*buffer_id_return = index;
|
||||
*buffer_addr_return = shm_channel->buffers[index];
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
}
|
||||
|
||||
*buffer_id_return = -1;
|
||||
*buffer_addr_return = NULL;
|
||||
if (bytes_read == 0)
|
||||
return SANE_STATUS_EOF;
|
||||
else
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
}
|
||||
|
||||
/** Pass a filled shared memory buffer to the reader process.
|
||||
*
|
||||
* @param shm_channel Shared memory channel object.
|
||||
* @param buffer_id Buffer identifier from shm_channel_writer_put_buffer().
|
||||
* @param buffer_bytes Number of data bytes in the buffer.
|
||||
*
|
||||
* @return
|
||||
* - SANE_STATUS_GOOD - the buffer was successfully queued.
|
||||
* - SANE_STATUS_IO_ERROR - the reader process has closed its half of the
|
||||
* channel, or another I/O error occured.
|
||||
*/
|
||||
SANE_Status
|
||||
shm_channel_writer_put_buffer (Shm_Channel * shm_channel,
|
||||
SANE_Int buffer_id, SANE_Int buffer_bytes)
|
||||
{
|
||||
SANE_Byte buf_index;
|
||||
int bytes_written;
|
||||
|
||||
SHM_CHANNEL_CHECK (shm_channel, "shm_channel_writer_put_buffer");
|
||||
|
||||
if (buffer_id < 0 || buffer_id >= shm_channel->buf_count)
|
||||
{
|
||||
DBG (3, "shm_channel_writer_put_buffer: BUG: buffer_id=%d\n",
|
||||
buffer_id);
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
shm_channel->buffer_bytes[buffer_id] = buffer_bytes;
|
||||
|
||||
buf_index = (SANE_Byte) buffer_id;
|
||||
do
|
||||
bytes_written = write (shm_channel->writer_put_pipe[1], &buf_index, 1);
|
||||
while ((bytes_written == 0) || (bytes_written == -1 && errno == EINTR));
|
||||
|
||||
if (bytes_written == 1)
|
||||
return SANE_STATUS_GOOD;
|
||||
else
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
}
|
||||
|
||||
/** Close the writing half of the shared memory channel.
|
||||
*
|
||||
* @param shm_channel Shared memory channel object.
|
||||
*/
|
||||
SANE_Status
|
||||
shm_channel_writer_close (Shm_Channel * shm_channel)
|
||||
{
|
||||
SHM_CHANNEL_CHECK (shm_channel, "shm_channel_writer_close");
|
||||
|
||||
shm_channel_fd_safe_close (&shm_channel->writer_put_pipe[1]);
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
/** Initialize the shared memory channel in the reader process.
|
||||
*
|
||||
* This function should be called after the fork in the process which will
|
||||
* read data from the channel.
|
||||
*
|
||||
* @param shm_channel Shared memory channel object.
|
||||
*/
|
||||
SANE_Status
|
||||
shm_channel_reader_init (Shm_Channel * shm_channel)
|
||||
{
|
||||
SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_init");
|
||||
|
||||
shm_channel_fd_safe_close (&shm_channel->writer_put_pipe[1]);
|
||||
|
||||
/* Don't close reader_put_pipe[0] here. Otherwise, if the channel writer
|
||||
* process dies early, this process might get SIGPIPE - and I don't want to
|
||||
* mess with signals in the main process. */
|
||||
/* shm_channel_fd_safe_close (&shm_channel->reader_put_pipe[0]); */
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/** Set non-blocking or blocking mode for the reading half of the shared memory
|
||||
* channel.
|
||||
*
|
||||
* @param shm_channel Shared memory channel object.
|
||||
* @param non_blocking SANE_TRUE to make the channel non-blocking, SANE_FALSE
|
||||
* to set blocking mode.
|
||||
*
|
||||
* @return
|
||||
* - SANE_STATUS_GOOD - the requested mode was set successfully.
|
||||
* - SANE_STATUS_IO_ERROR - error setting the requested mode.
|
||||
*/
|
||||
SANE_Status
|
||||
shm_channel_reader_set_io_mode (Shm_Channel * shm_channel,
|
||||
SANE_Bool non_blocking)
|
||||
{
|
||||
SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_set_io_mode");
|
||||
|
||||
return shm_channel_fd_set_non_blocking (shm_channel->writer_put_pipe[0],
|
||||
non_blocking);
|
||||
}
|
||||
|
||||
/** Get the file descriptor which will signal when some data is available in
|
||||
* the shared memory channel.
|
||||
*
|
||||
* The returned file descriptor can be used in select() or poll(). When one of
|
||||
* these functions signals that the file descriptor is ready for reading,
|
||||
* shm_channel_reader_get_buffer() should return some data without blocking.
|
||||
*
|
||||
* @param shm_channel Shared memory channel object.
|
||||
* @param fd_return The returned file descriptor.
|
||||
*
|
||||
* @return
|
||||
* - SANE_STATUS_GOOD - the file descriptor was returned.
|
||||
*/
|
||||
SANE_Status
|
||||
shm_channel_reader_get_select_fd (Shm_Channel * shm_channel,
|
||||
SANE_Int * fd_return)
|
||||
{
|
||||
SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_get_select_fd");
|
||||
|
||||
*fd_return = shm_channel->writer_put_pipe[0];
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Start reading from the shared memory channel.
|
||||
*
|
||||
* A newly initialized shared memory channel is stopped - the writer process
|
||||
* will block on shm_channel_writer_get_buffer(). This function will pass all
|
||||
* available buffers to the writer process, starting the transfer through the
|
||||
* channel.
|
||||
*
|
||||
* @param shm_channel Shared memory channel object.
|
||||
*/
|
||||
SANE_Status
|
||||
shm_channel_reader_start (Shm_Channel * shm_channel)
|
||||
{
|
||||
int i, bytes_written;
|
||||
SANE_Byte buffer_id;
|
||||
|
||||
SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_start");
|
||||
|
||||
for (i = 0; i < shm_channel->buf_count; ++i)
|
||||
{
|
||||
buffer_id = i;
|
||||
do
|
||||
bytes_written =
|
||||
write (shm_channel->reader_put_pipe[1], &buffer_id, 1);
|
||||
while ((bytes_written == 0) || (bytes_written == -1 && errno == EINTR));
|
||||
|
||||
if (bytes_written == -1)
|
||||
{
|
||||
DBG (3, "shm_channel_reader_start: write error at buffer %d: %s\n",
|
||||
i, strerror (errno));
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/** Get the next shared memory buffer passed from the writer process.
|
||||
*
|
||||
* If the channel was not set to non-blocking mode, this function will block
|
||||
* until the data buffer arrives from the writer process. In non-blocking mode
|
||||
* this function will place NULL in @a *buffer_addr_return and return
|
||||
* SANE_STATUS_GOOD if a buffer is not available immediately.
|
||||
*
|
||||
* After successful completion of this function (return value is
|
||||
* SANE_STATUS_GOOD and @a *buffer_addr_return is not NULL) the reader process
|
||||
* should process the data in the buffer and then call
|
||||
* shm_channel_reader_put_buffer() to release the buffer.
|
||||
*
|
||||
* @param shm_channel Shared memory channel object.
|
||||
* @param buffer_id_return Returned buffer identifier.
|
||||
* @param buffer_addr_return Returned buffer address.
|
||||
* @param buffer_bytes_return Returned number of data bytes in the buffer.
|
||||
*
|
||||
* @return
|
||||
* - SANE_STATUS_GOOD - no error. If the channel was in non-blocking mode, @a
|
||||
* *buffer_id_return may be NULL, indicating that no data was available.
|
||||
* Otherwise, @a *buffer_id_return, @a *buffer_addr_return and @a
|
||||
* *buffer_bytes return are filled with valid values.
|
||||
* - SANE_STATUS_EOF - the writer process has closed its half of the channel.
|
||||
* - SANE_STATUS_IO_ERROR - an I/O error occured.
|
||||
*/
|
||||
SANE_Status
|
||||
shm_channel_reader_get_buffer (Shm_Channel * shm_channel,
|
||||
SANE_Int * buffer_id_return,
|
||||
SANE_Byte ** buffer_addr_return,
|
||||
SANE_Int * buffer_bytes_return)
|
||||
{
|
||||
SANE_Byte buf_index;
|
||||
int bytes_read;
|
||||
|
||||
SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_get_buffer");
|
||||
|
||||
do
|
||||
bytes_read = read (shm_channel->writer_put_pipe[0], &buf_index, 1);
|
||||
while (bytes_read == -1 && errno == EINTR);
|
||||
|
||||
if (bytes_read == 1)
|
||||
{
|
||||
SANE_Int index = buf_index;
|
||||
if (index < shm_channel->buf_count)
|
||||
{
|
||||
*buffer_id_return = index;
|
||||
*buffer_addr_return = shm_channel->buffers[index];
|
||||
*buffer_bytes_return = shm_channel->buffer_bytes[index];
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
}
|
||||
|
||||
*buffer_id_return = -1;
|
||||
*buffer_addr_return = NULL;
|
||||
*buffer_bytes_return = 0;
|
||||
if (bytes_read == 0)
|
||||
return SANE_STATUS_EOF;
|
||||
else
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
}
|
||||
|
||||
/** Release a shared memory buffer received by the reader process.
|
||||
*
|
||||
* This function must be called after shm_channel_reader_get_buffer() to
|
||||
* release the buffer and make it available for transferring the next portion
|
||||
* of data.
|
||||
*
|
||||
* After calling this function the reader process must not access the buffer
|
||||
* contents; any data which may be needed later should be copied into some
|
||||
* other place beforehand.
|
||||
*
|
||||
* @param shm_channel Shared memory channel object.
|
||||
* @param buffer_id Buffer identifier from shm_channel_reader_get_buffer().
|
||||
*
|
||||
* @return
|
||||
* - SANE_STATUS_GOOD - the buffer was successfully released.
|
||||
* - SANE_STATUS_IO_ERROR - the writer process has closed its half of the
|
||||
* channel, or an unexpected I/O error occured.
|
||||
*/
|
||||
SANE_Status
|
||||
shm_channel_reader_put_buffer (Shm_Channel * shm_channel, SANE_Int buffer_id)
|
||||
{
|
||||
SANE_Byte buf_index;
|
||||
int bytes_written;
|
||||
|
||||
SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_put_buffer");
|
||||
|
||||
if (buffer_id < 0 || buffer_id >= shm_channel->buf_count)
|
||||
{
|
||||
DBG (3, "shm_channel_reader_put_buffer: BUG: buffer_id=%d\n",
|
||||
buffer_id);
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
buf_index = (SANE_Byte) buffer_id;
|
||||
do
|
||||
bytes_written = write (shm_channel->reader_put_pipe[1], &buf_index, 1);
|
||||
while ((bytes_written == 0) || (bytes_written == -1 && errno == EINTR));
|
||||
|
||||
if (bytes_written == 1)
|
||||
return SANE_STATUS_GOOD;
|
||||
else
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/** Close the reading half of the shared memory channel.
|
||||
*
|
||||
* @param shm_channel Shared memory channel object.
|
||||
*/
|
||||
SANE_Status
|
||||
shm_channel_reader_close (Shm_Channel * shm_channel)
|
||||
{
|
||||
SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_close");
|
||||
|
||||
shm_channel_fd_safe_close (&shm_channel->reader_put_pipe[1]);
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
#endif
|
||||
/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
|
|
@ -0,0 +1,106 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2002 Sergey Vlasov <vsu@altlinux.ru>
|
||||
|
||||
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 GT68XX_SHM_CHANNEL_H
|
||||
#define GT68XX_SHM_CHANNEL_H
|
||||
|
||||
/** @file
|
||||
* @brief Shared memory channel support.
|
||||
*/
|
||||
|
||||
#include "../include/sane/sane.h"
|
||||
|
||||
typedef struct Shm_Channel Shm_Channel;
|
||||
|
||||
static SANE_Status
|
||||
shm_channel_new (SANE_Int buf_size,
|
||||
SANE_Int buf_count, Shm_Channel ** shm_channel_return);
|
||||
|
||||
static SANE_Status shm_channel_free (Shm_Channel * shm_channel);
|
||||
|
||||
|
||||
static SANE_Status shm_channel_writer_init (Shm_Channel * shm_channel);
|
||||
|
||||
static SANE_Status
|
||||
shm_channel_writer_get_buffer (Shm_Channel * shm_channel,
|
||||
SANE_Int * buffer_id_return,
|
||||
SANE_Byte ** buffer_addr_return);
|
||||
|
||||
static SANE_Status
|
||||
shm_channel_writer_put_buffer (Shm_Channel * shm_channel,
|
||||
SANE_Int buffer_id, SANE_Int buffer_bytes);
|
||||
|
||||
static SANE_Status shm_channel_writer_close (Shm_Channel * shm_channel);
|
||||
|
||||
|
||||
static SANE_Status shm_channel_reader_init (Shm_Channel * shm_channel);
|
||||
|
||||
#if 0
|
||||
static SANE_Status
|
||||
shm_channel_reader_set_io_mode (Shm_Channel * shm_channel,
|
||||
SANE_Bool non_blocking);
|
||||
|
||||
static SANE_Status
|
||||
shm_channel_reader_get_select_fd (Shm_Channel * shm_channel,
|
||||
SANE_Int * fd_return);
|
||||
|
||||
#endif
|
||||
|
||||
static SANE_Status shm_channel_reader_start (Shm_Channel * shm_channel);
|
||||
|
||||
static SANE_Status
|
||||
shm_channel_reader_get_buffer (Shm_Channel * shm_channel,
|
||||
SANE_Int * buffer_id_return,
|
||||
SANE_Byte ** buffer_addr_return,
|
||||
SANE_Int * buffer_bytes_return);
|
||||
|
||||
static SANE_Status
|
||||
shm_channel_reader_put_buffer (Shm_Channel * shm_channel, SANE_Int buffer_id);
|
||||
|
||||
#if 0
|
||||
static SANE_Status shm_channel_reader_close (Shm_Channel * shm_channel);
|
||||
#endif
|
||||
|
||||
#endif /* not GT68XX_SHM_CHANNEL_H */
|
||||
|
||||
/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
|
Ładowanie…
Reference in New Issue