kopia lustrzana https://gitlab.com/sane-project/backends
Merge branch 'master' into 'release/1.0.30'
# Conflicts: # NEWSmerge-requests/457/head
commit
bfea8a1a82
|
@ -1,12 +1,12 @@
|
|||
# .gitlab-ci.yml -- to test some source code build scenarios
|
||||
# Copyright (C) 2016-2019 Olaf Meeuwissen
|
||||
# Copyright (C) 2016-2020 Olaf Meeuwissen
|
||||
#
|
||||
# License: GPL-3.0+
|
||||
|
||||
variables:
|
||||
REGISTRY_HUB: "registry.gitlab.com/sane-project/ci-envs"
|
||||
CONFIGURE_MINI: "--enable-silent-rules"
|
||||
CONFIGURE_FULL: "--with-usb --enable-avahi --enable-pnm-backend --with-libcurl"
|
||||
CONFIGURE_FULL: "--with-usb --with-avahi --enable-pnm-backend --with-libcurl --with-poppler-glib"
|
||||
|
||||
stages:
|
||||
- tarball
|
||||
|
@ -76,8 +76,8 @@ debian-10-full:
|
|||
- doc/sanei-html
|
||||
expire_in: 1 day
|
||||
|
||||
fedora-31-clang:
|
||||
image: $REGISTRY_HUB:fedora-31-clang
|
||||
fedora-32-clang:
|
||||
image: $REGISTRY_HUB:fedora-32-clang
|
||||
variables:
|
||||
CONFIGURE_OPTS: "$CONFIGURE_MINI $CONFIGURE_FULL"
|
||||
<<: *compile_definition
|
||||
|
@ -88,6 +88,13 @@ alpine-3.11-musl:
|
|||
CONFIGURE_OPTS: "$CONFIGURE_MINI $CONFIGURE_FULL"
|
||||
<<: *compile_definition
|
||||
|
||||
ubuntu-16.04-lts:
|
||||
image: $REGISTRY_HUB:ubuntu-xenial-dist
|
||||
variables:
|
||||
CONFIGURE_OPTS: "$CONFIGURE_MINI $CONFIGURE_FULL"
|
||||
MAKE_FLAGS: "CFLAGS=-Werror CXXFLAGS=-Werror"
|
||||
<<: *compile_definition
|
||||
|
||||
# This snapshot stage job makes sure that the source tarball has all
|
||||
# it needs to rebuild itself, install everything built and cleans up
|
||||
# without leaving any droppings behind when uninstalling. The build
|
||||
|
|
5
AUTHORS
5
AUTHORS
|
@ -1,7 +1,3 @@
|
|||
Authors of the SANE standard:
|
||||
|
||||
Andreas Beck and David Mosberger
|
||||
|
||||
Backends:
|
||||
|
||||
abaton: David Huggins-Daines
|
||||
|
@ -17,6 +13,7 @@ Backends:
|
|||
Mitsuru Okaniwa, Ulrich Deiters
|
||||
canon630u: Nathan Rutman
|
||||
canon_dr: m. allan noah (*)
|
||||
canon_lide70: Juergen Ernst, pimvantend (*)
|
||||
canon_pp: Matthew Duggan, Simon Krix
|
||||
cardscan: m. allan noah (*)
|
||||
coolscan: Didier Carlier, Andreas Rick
|
||||
|
|
|
@ -24,6 +24,8 @@ $ make install
|
|||
- libpng-dev or similar
|
||||
- libcurl4-gnutls-dev or similar
|
||||
- libxml2-dev or similar
|
||||
- libsnmp-dev or similar
|
||||
- libpoppler-glib-dev or similar
|
||||
|
||||
2.2. Get the latest SANE backend from git:
|
||||
You can download "daily git snapshot" from here:
|
||||
|
|
3
LICENSE
3
LICENSE
|
@ -30,6 +30,9 @@ terms:
|
|||
to implement SANE interface conforming applications or libraries in
|
||||
any way he or she sees fit.
|
||||
|
||||
The standard is maintained at https://gitlab.com/sane-project/standard
|
||||
and published at https://sane-project.gitlab.io/standard/.
|
||||
|
||||
Frequently Asked Questions about the SANE licensing:
|
||||
|
||||
* Why don't you use the GNU LPGL ?
|
||||
|
|
21
NEWS
21
NEWS
|
@ -1,5 +1,26 @@
|
|||
<!-- -*- Mode: markdown -*- -->
|
||||
|
||||
## New with the next release
|
||||
|
||||
### Backends
|
||||
|
||||
- adds an `canon_lide70` backend
|
||||
|
||||
### Documentation
|
||||
|
||||
- removes the SANE Standard. This is now maintained as a separate
|
||||
project at https://gitlab.com/sane-project/standard. HTML and PDF
|
||||
versions can be found at https://sane-project.gitlab.io/standard/.
|
||||
|
||||
### Build
|
||||
|
||||
- removes the `--with-api-spec` option from `configure`
|
||||
- replaces the `--enable-avahi` option with an `--with-avahi` that
|
||||
defaults to enabling if possible. If the option is given and the
|
||||
required support is not available, `configure` will exit with an
|
||||
error.
|
||||
|
||||
|
||||
## New with 1.0.30 (released 2020-05-17)
|
||||
|
||||
This release fixes several security related issues and a build issue.
|
||||
|
|
2
README
2
README
|
@ -57,6 +57,8 @@ installed.
|
|||
|
||||
- libgphoto2 (>=2.0): For the gphoto2 backend.
|
||||
|
||||
- a C++11 compliant C++ compiler for the genesys backend.
|
||||
|
||||
If you got the source straight from the git repository, as opposed to
|
||||
a source tarball, you will need a few more utilities. These utilities
|
||||
should normally *not* be needed for source archives downloaded from
|
||||
|
|
|
@ -613,7 +613,7 @@ for be in ${BACKENDS}; do
|
|||
;;
|
||||
|
||||
escl)
|
||||
if test "x${enable_avahi}" != "xyes"; then
|
||||
if test "x${with_avahi}" != "xyes"; then
|
||||
echo "*** $be backend requires AVAHI library - $DISABLE_MSG"
|
||||
backend_supported="no"
|
||||
fi
|
||||
|
@ -629,7 +629,14 @@ for be in ${BACKENDS}; do
|
|||
if test "x${sane_cv_use_libjpeg}" != "xyes"; then
|
||||
echo "*** $be backend currently requires JPEG library - $DISABLE_MSG"
|
||||
backend_supported="no"
|
||||
else
|
||||
if test "x${ac_cv_func_jpeg_crop_scanline}" != "xyes" \
|
||||
|| test "x${ac_cv_func_jpeg_skip_scanlines}" != "xyes"; then
|
||||
echo "*** $be backend requires a newer JPEG library - $DISABLE_MSG"
|
||||
backend_supported="no"
|
||||
fi
|
||||
fi
|
||||
|
||||
;;
|
||||
|
||||
gphoto2)
|
||||
|
|
|
@ -65,6 +65,7 @@ EXTRA_DIST += saned.conf.in
|
|||
BACKEND_CONFS= abaton.conf agfafocus.conf apple.conf artec.conf \
|
||||
artec_eplus48u.conf avision.conf bh.conf \
|
||||
canon630u.conf canon.conf canon_dr.conf \
|
||||
canon_lide70.conf \
|
||||
canon_pp.conf cardscan.conf coolscan2.conf coolscan3.conf \
|
||||
coolscan.conf dc210.conf dc240.conf dc25.conf \
|
||||
dell1600n_net.conf dmc.conf epjitsu.conf epson2.conf \
|
||||
|
@ -157,6 +158,7 @@ be_convenience_libs = libabaton.la libagfafocus.la \
|
|||
libapple.la libartec.la libartec_eplus48u.la \
|
||||
libas6e.la libavision.la libbh.la \
|
||||
libcanon.la libcanon630u.la libcanon_dr.la \
|
||||
libcanon_lide70.la \
|
||||
libcanon_pp.la libcardscan.la libcoolscan.la \
|
||||
libcoolscan2.la libcoolscan3.la libdc25.la \
|
||||
libdc210.la libdc240.la libdell1600n_net.la \
|
||||
|
@ -190,6 +192,7 @@ be_dlopen_libs = libsane-abaton.la libsane-agfafocus.la \
|
|||
libsane-apple.la libsane-artec.la libsane-artec_eplus48u.la \
|
||||
libsane-as6e.la libsane-avision.la libsane-bh.la \
|
||||
libsane-canon.la libsane-canon630u.la libsane-canon_dr.la \
|
||||
libsane-canon_lide70.la \
|
||||
libsane-canon_pp.la libsane-cardscan.la libsane-coolscan.la \
|
||||
libsane-coolscan2.la libsane-coolscan3.la libsane-dc25.la \
|
||||
libsane-dc210.la libsane-dc240.la libsane-dell1600n_net.la \
|
||||
|
@ -344,6 +347,17 @@ libsane_canon_dr_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
|||
libsane_canon_dr_la_LIBADD = $(COMMON_LIBS) libcanon_dr.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_magic.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += canon_dr.conf.in
|
||||
|
||||
libcanon_lide70_la_SOURCES = canon_lide70.c
|
||||
libcanon_lide70_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon_lide70
|
||||
|
||||
nodist_libsane_canon_lide70_la_SOURCES = canon_lide70-s.c
|
||||
libsane_canon_lide70_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon_lide70
|
||||
libsane_canon_lide70_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_canon_lide70_la_LIBADD = $(COMMON_LIBS) libcanon_lide70.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += canon_lide70.conf.in
|
||||
# TODO: Why are this distributed but not compiled?
|
||||
EXTRA_DIST += canon_lide70-common.c
|
||||
|
||||
libcanon_pp_la_SOURCES = canon_pp.c canon_pp.h canon_pp-io.c canon_pp-io.h canon_pp-dev.c canon_pp-dev.h
|
||||
libcanon_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon_pp
|
||||
|
||||
|
@ -437,13 +451,26 @@ EXTRA_DIST += dmc.conf.in
|
|||
if have_libavahi
|
||||
if have_libcurl
|
||||
if have_libxml2
|
||||
libescl_la_SOURCES = escl/escl.c escl/escl_capabilities.c escl/escl_devices.c escl/escl.h escl/escl_newjob.c escl/escl_reset.c escl/escl_scan.c escl/escl_status.c escl/escl_jpeg.c escl/escl_png.c escl/escl_tiff.c
|
||||
libescl_la_CPPFLAGS = $(AM_CPPFLAGS) $(JPEG_CFLAGS) $(PNG_CFLAGS) $(TIFF_CFLAGS) $(XML_CFLAGS) $(libcurl_CFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=escl
|
||||
libescl_la_SOURCES = escl/escl.c \
|
||||
escl/escl_capabilities.c \
|
||||
escl/escl_devices.c \
|
||||
escl/escl.h \
|
||||
escl/escl_newjob.c \
|
||||
escl/escl_reset.c \
|
||||
escl/escl_scan.c \
|
||||
escl/escl_status.c \
|
||||
escl/escl_jpeg.c \
|
||||
escl/escl_png.c \
|
||||
escl/escl_tiff.c \
|
||||
escl/escl_pdf.c \
|
||||
escl/escl_crop.c
|
||||
libescl_la_CPPFLAGS = $(AM_CPPFLAGS) $(JPEG_CFLAGS) $(PNG_CFLAGS) $(TIFF_CFLAGS) $(POPPLER_GLIB_CFLAGS) $(XML_CFLAGS) $(libcurl_CFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=escl
|
||||
|
||||
nodist_libsane_escl_la_SOURCES = escl-s.c
|
||||
libsane_escl_la_CPPFLAGS = $(AM_CPPFLAGS) $(JPEG_CFLAGS) $(PNG_CFLAGS) $(TIFF_CFLAGS) $(XML_CFLAGS) $(libcurl_CFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=escl
|
||||
libsane_escl_la_CPPFLAGS = $(AM_CPPFLAGS) $(JPEG_CFLAGS) $(PNG_CFLAGS) $(TIFF_CFLAGS) $(POPPLER_GLIB_CFLAGS) $(XML_CFLAGS) $(libcurl_CFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=escl
|
||||
libsane_escl_la_CFLAGS = $(AM_CFLAGS) $(JPEG_CFLAGS) $(PNG_CFLAGS) $(TIFF_CFLAGS) $(POPPLER_GLIB_CFLAGS) $(XML_CFLAGS) $(libcurl_CFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=escl
|
||||
libsane_escl_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_escl_la_LIBADD = $(COMMON_LIBS) libescl.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(JPEG_LIBS) $(PNG_LIBS) $(TIFF_LIBS) $(XML_LIBS) $(libcurl_LIBS) $(AVAHI_LIBS)
|
||||
libsane_escl_la_LIBADD = $(COMMON_LIBS) libescl.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(MATH_LIB) $(JPEG_LIBS) $(PNG_LIBS) $(TIFF_LIBS) $(POPPLER_GLIB_LIBS) $(XML_LIBS) $(libcurl_LIBS) $(AVAHI_LIBS)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
@ -504,6 +531,7 @@ libgenesys_la_SOURCES = genesys/genesys.cpp genesys/genesys.h \
|
|||
genesys/buffer.h genesys/buffer.cpp \
|
||||
genesys/calibration.h \
|
||||
genesys/command_set.h \
|
||||
genesys/command_set_common.h genesys/command_set_common.cpp \
|
||||
genesys/conv.h genesys/conv.cpp \
|
||||
genesys/device.h genesys/device.cpp \
|
||||
genesys/enums.h genesys/enums.cpp \
|
||||
|
@ -512,6 +540,7 @@ libgenesys_la_SOURCES = genesys/genesys.cpp genesys/genesys.h \
|
|||
genesys/gl646.cpp genesys/gl646.h genesys/gl646_registers.h \
|
||||
genesys/gl124.cpp genesys/gl124.h genesys/gl124_registers.h \
|
||||
genesys/gl841.cpp genesys/gl841.h genesys/gl841_registers.h \
|
||||
genesys/gl842.cpp genesys/gl842.h genesys/gl842_registers.h \
|
||||
genesys/gl843.cpp genesys/gl843.h genesys/gl843_registers.h \
|
||||
genesys/gl846.cpp genesys/gl846.h genesys/gl846_registers.h \
|
||||
genesys/gl847.cpp genesys/gl847.h genesys/gl847_registers.h \
|
||||
|
@ -532,15 +561,16 @@ libgenesys_la_SOURCES = genesys/genesys.cpp genesys/genesys.h \
|
|||
genesys/status.h genesys/status.cpp \
|
||||
genesys/tables_frontend.cpp \
|
||||
genesys/tables_gpo.cpp \
|
||||
genesys/tables_memory_layout.cpp \
|
||||
genesys/tables_model.cpp \
|
||||
genesys/tables_motor.cpp \
|
||||
genesys/tables_motor_profile.cpp \
|
||||
genesys/tables_sensor.cpp \
|
||||
genesys/test_scanner_interface.h genesys/test_scanner_interface.cpp \
|
||||
genesys/test_settings.h genesys/test_settings.cpp \
|
||||
genesys/test_usb_device.h genesys/test_usb_device.cpp \
|
||||
genesys/usb_device.h genesys/usb_device.cpp \
|
||||
genesys/low.cpp genesys/low.h \
|
||||
genesys/value_filter.h \
|
||||
genesys/utilities.h
|
||||
|
||||
libgenesys_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=genesys
|
||||
|
@ -682,10 +712,10 @@ libsane_kodak_la_LIBADD = $(COMMON_LIBS) libkodak.la ../sanei/sanei_init_debug.l
|
|||
EXTRA_DIST += kodak.conf.in
|
||||
|
||||
libkodakaio_la_SOURCES = kodakaio.c kodakaio.h
|
||||
libkodakaio_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kodakaio
|
||||
libkodakaio_la_CPPFLAGS = $(AM_CPPFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=kodakaio
|
||||
|
||||
nodist_libsane_kodakaio_la_SOURCES = kodakaio-s.c
|
||||
libsane_kodakaio_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kodakaio
|
||||
libsane_kodakaio_la_CPPFLAGS = $(AM_CPPFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=kodakaio
|
||||
libsane_kodakaio_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_kodakaio_la_LIBADD = $(COMMON_LIBS) libkodakaio.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo $(USB_LIBS) $(SOCKET_LIBS) $(AVAHI_LIBS) $(MATH_LIB) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += kodakaio.conf.in
|
||||
|
@ -904,12 +934,12 @@ libpixma_la_SOURCES = pixma/pixma.c \
|
|||
pixma/pixma_bjnp.h \
|
||||
pixma/pixma_bjnp_private.h \
|
||||
pixma/pixma_rename.h
|
||||
libpixma_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pixma
|
||||
libpixma_la_CPPFLAGS = $(AM_CPPFLAGS) $(XML_CFLAGS) -DBACKEND_NAME=pixma
|
||||
|
||||
nodist_libsane_pixma_la_SOURCES = pixma-s.c
|
||||
libsane_pixma_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pixma
|
||||
libsane_pixma_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_pixma_la_LIBADD = $(COMMON_LIBS) libpixma.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(SANEI_SANEI_JPEG_LO) $(JPEG_LIBS) $(MATH_LIB) $(SOCKET_LIBS) $(USB_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS)
|
||||
libsane_pixma_la_LIBADD = $(COMMON_LIBS) libpixma.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(SANEI_SANEI_JPEG_LO) $(JPEG_LIBS) $(XML_LIBS) $(MATH_LIB) $(SOCKET_LIBS) $(USB_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += pixma.conf.in
|
||||
# included in pixma.c
|
||||
EXTRA_DIST += pixma/pixma_sane_options.c pixma/pixma_sane_options.h
|
||||
|
|
|
@ -4088,6 +4088,8 @@ get_double ( &(result[48] ) ));
|
|||
dev->inquiry_button_control = BIT (result[50], 6) | BIT (result[51],2);
|
||||
|
||||
dev->inquiry_exposure_control = BIT(result[51],7);
|
||||
if (dev->scanner_type != AV_FILM && !(dev->hw->feature_type & AV_FORCE_FILM))
|
||||
dev->inquiry_exposure_control = 0;
|
||||
dev->inquiry_max_shading_target = get_double ( &(result[75]) );
|
||||
|
||||
dev->inquiry_color_boundary = result[54];
|
||||
|
@ -6221,7 +6223,12 @@ do_cancel (Avision_Scanner* s)
|
|||
s->prepared = s->scanning = SANE_FALSE;
|
||||
s->duplex_rear_valid = SANE_FALSE;
|
||||
s->page = 0;
|
||||
s->cancelled = 1;
|
||||
s->cancelled = SANE_TRUE;
|
||||
|
||||
if (s->read_fds >= 0) {
|
||||
close(s->read_fds);
|
||||
s->read_fds = -1;
|
||||
}
|
||||
|
||||
if (sanei_thread_is_valid (s->reader_pid)) {
|
||||
int exit_status;
|
||||
|
@ -6716,6 +6723,7 @@ reader_process (void *data)
|
|||
sigset_t sigterm_set;
|
||||
sigset_t ignore_set;
|
||||
struct SIGACTION act;
|
||||
int old;
|
||||
|
||||
FILE* fp;
|
||||
FILE* rear_fp = 0; /* used to store the deinterlaced rear data */
|
||||
|
@ -6757,21 +6765,30 @@ reader_process (void *data)
|
|||
|
||||
DBG (3, "reader_process:\n");
|
||||
|
||||
if (sanei_thread_is_forked())
|
||||
if (sanei_thread_is_forked()) {
|
||||
close (s->read_fds);
|
||||
s->read_fds = -1;
|
||||
|
||||
sigfillset (&ignore_set);
|
||||
sigdelset (&ignore_set, SIGTERM);
|
||||
sigfillset (&ignore_set);
|
||||
sigdelset (&ignore_set, SIGTERM);
|
||||
#if defined (__APPLE__) && defined (__MACH__)
|
||||
sigdelset (&ignore_set, SIGUSR2);
|
||||
sigdelset (&ignore_set, SIGUSR2);
|
||||
#endif
|
||||
sigprocmask (SIG_SETMASK, &ignore_set, 0);
|
||||
sigprocmask (SIG_SETMASK, &ignore_set, 0);
|
||||
|
||||
memset (&act, 0, sizeof (act));
|
||||
sigaction (SIGTERM, &act, 0);
|
||||
memset (&act, 0, sizeof (act));
|
||||
sigaction (SIGTERM, &act, 0);
|
||||
|
||||
sigemptyset (&sigterm_set);
|
||||
sigaddset (&sigterm_set, SIGTERM);
|
||||
sigemptyset (&sigterm_set);
|
||||
sigaddset (&sigterm_set, SIGTERM);
|
||||
}
|
||||
#ifdef USE_PTHREAD
|
||||
else {
|
||||
int old;
|
||||
pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &old);
|
||||
pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
|
||||
}
|
||||
#endif
|
||||
|
||||
gray_mode = color_mode_is_shaded (s->c_mode);
|
||||
|
||||
|
@ -6958,9 +6975,22 @@ reader_process (void *data)
|
|||
(u_long) processed_bytes, (u_long) total_size);
|
||||
DBG (5, "reader_process: this_read: %lu\n", (u_long) this_read);
|
||||
|
||||
sigprocmask (SIG_BLOCK, &sigterm_set, 0);
|
||||
if (sanei_thread_is_forked())
|
||||
sigprocmask (SIG_BLOCK, &sigterm_set, 0);
|
||||
#ifdef USE_PTHREAD
|
||||
else
|
||||
pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &old);
|
||||
#endif
|
||||
|
||||
status = read_data (s, stripe_data + stripe_fill, &this_read);
|
||||
sigprocmask (SIG_UNBLOCK, &sigterm_set, 0);
|
||||
|
||||
if (sanei_thread_is_forked())
|
||||
sigprocmask (SIG_UNBLOCK, &sigterm_set, 0);
|
||||
#ifdef USE_PTHREAD
|
||||
else
|
||||
pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &old);
|
||||
#endif
|
||||
|
||||
|
||||
/* only EOF on the second stripe, as otherwise the rear page
|
||||
is shorter */
|
||||
|
@ -8332,7 +8362,7 @@ sane_start (SANE_Handle handle)
|
|||
return SANE_STATUS_DEVICE_BUSY;
|
||||
|
||||
/* Clear cancellation status */
|
||||
s->cancelled = 0;
|
||||
s->cancelled = SANE_FALSE;
|
||||
|
||||
/* Make sure we have a current parameter set. Some of the
|
||||
parameters will be overwritten below, but that's OK. */
|
||||
|
@ -8560,8 +8590,10 @@ sane_start (SANE_Handle handle)
|
|||
DBG (3, "sane_start: starting thread\n");
|
||||
s->reader_pid = sanei_thread_begin (reader_process, (void *) s);
|
||||
|
||||
if (sanei_thread_is_forked())
|
||||
close (s->write_fds);
|
||||
if (sanei_thread_is_forked()) {
|
||||
close (s->write_fds);
|
||||
s->write_fds = -1;
|
||||
}
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,960 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
BACKEND canon_lide70
|
||||
|
||||
Copyright (C) 2019 Juergen Ernst and pimvantend.
|
||||
|
||||
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.
|
||||
|
||||
This file implements a SANE backend for the Canon CanoScan LiDE 70 */
|
||||
|
||||
#define BUILD 0
|
||||
#define MM_IN_INCH 25.4
|
||||
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "../include/sane/sane.h"
|
||||
#include "../include/sane/sanei.h"
|
||||
#include "../include/sane/saneopts.h"
|
||||
#include "../include/sane/sanei_config.h"
|
||||
#include "../include/sane/sanei_usb.h"
|
||||
#define BACKEND_NAME canon_lide70
|
||||
#define CANONUSB_CONFIG_FILE "canon_lide70.conf"
|
||||
#include "../include/sane/sanei_backend.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
opt_num_opts = 0,
|
||||
opt_mode_group,
|
||||
opt_threshold,
|
||||
opt_mode,
|
||||
opt_resolution,
|
||||
opt_non_blocking,
|
||||
opt_geometry_group,
|
||||
opt_tl_x,
|
||||
opt_tl_y,
|
||||
opt_br_x,
|
||||
opt_br_y,
|
||||
/* must come last: */
|
||||
num_options
|
||||
}
|
||||
canon_opts;
|
||||
|
||||
#include "canon_lide70-common.c"
|
||||
|
||||
static size_t
|
||||
max_string_size (const SANE_String_Const strings[])
|
||||
{
|
||||
size_t size, max_size = 0;
|
||||
SANE_Int i;
|
||||
|
||||
for (i = 0; strings[i]; ++i)
|
||||
{
|
||||
size = strlen (strings[i]) + 1;
|
||||
if (size > max_size)
|
||||
max_size = size;
|
||||
}
|
||||
return max_size;
|
||||
}
|
||||
|
||||
static SANE_String_Const mode_list[] = {
|
||||
SANE_VALUE_SCAN_MODE_COLOR,
|
||||
SANE_VALUE_SCAN_MODE_GRAY,
|
||||
SANE_VALUE_SCAN_MODE_LINEART,
|
||||
0
|
||||
};
|
||||
|
||||
static SANE_Fixed init_tl_x = SANE_FIX (0.0);
|
||||
static SANE_Fixed init_tl_y = SANE_FIX (0.0);
|
||||
static SANE_Fixed init_br_x = SANE_FIX (80.0);
|
||||
static SANE_Fixed init_br_y = SANE_FIX (100.0);
|
||||
static SANE_Int init_threshold = 75;
|
||||
static SANE_Int init_resolution = 600;
|
||||
static SANE_String init_mode = SANE_VALUE_SCAN_MODE_COLOR;
|
||||
static SANE_Int init_graymode = 0;
|
||||
static SANE_Bool init_non_blocking = SANE_FALSE;
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
/*
|
||||
Scan range
|
||||
*/
|
||||
|
||||
static const SANE_Range widthRange = {
|
||||
0, /* minimum */
|
||||
SANE_FIX (CANON_MAX_WIDTH * MM_IN_INCH / 600), /* maximum */
|
||||
0 /* quantization */
|
||||
};
|
||||
|
||||
static const SANE_Range heightRange = {
|
||||
0, /* minimum */
|
||||
/* SANE_FIX (CANON_MAX_HEIGHT * MM_IN_INCH / 600 - TOP_EDGE ), maximum */
|
||||
SANE_FIX (297.0),
|
||||
0 /* quantization */
|
||||
};
|
||||
|
||||
static const SANE_Range threshold_range = {
|
||||
0,
|
||||
100,
|
||||
1
|
||||
};
|
||||
|
||||
static SANE_Int resolution_list[] = { 5,
|
||||
75,
|
||||
150,
|
||||
300,
|
||||
600,
|
||||
1200
|
||||
};
|
||||
|
||||
typedef struct Canon_Device
|
||||
{
|
||||
struct Canon_Device *next;
|
||||
SANE_String name;
|
||||
SANE_Device sane;
|
||||
}
|
||||
Canon_Device;
|
||||
|
||||
/* Canon_Scanner is the type used for the sane handle */
|
||||
typedef struct Canon_Scanner
|
||||
{
|
||||
struct Canon_Scanner *next;
|
||||
Canon_Device *device;
|
||||
CANON_Handle scan;
|
||||
}
|
||||
Canon_Scanner;
|
||||
|
||||
static int num_devices = 0;
|
||||
static const SANE_Device **devlist = NULL;
|
||||
static Canon_Device *first_dev = NULL;
|
||||
static Canon_Scanner *first_handle = NULL;
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
static SANE_Status
|
||||
attach_scanner (const char *devicename, Canon_Device ** devp)
|
||||
{
|
||||
CANON_Handle scan;
|
||||
Canon_Device *dev;
|
||||
SANE_Status status;
|
||||
|
||||
DBG (3, "attach_scanner: %s\n", devicename);
|
||||
|
||||
for (dev = first_dev; dev; dev = dev->next)
|
||||
{
|
||||
if (strcmp (dev->sane.name, devicename) == 0)
|
||||
{
|
||||
if (devp)
|
||||
*devp = dev;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
}
|
||||
|
||||
dev = malloc (sizeof (*dev));
|
||||
if (!dev)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
memset (dev, '\0', sizeof (Canon_Device)); /* clear structure */
|
||||
|
||||
DBG (4, "attach_scanner: opening %s\n", devicename);
|
||||
|
||||
status = CANON_open_device (&scan, devicename);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (1, "ERROR: attach_scanner: opening %s failed\n", devicename);
|
||||
free (dev);
|
||||
return status;
|
||||
}
|
||||
dev->name = strdup (devicename);
|
||||
dev->sane.name = dev->name;
|
||||
dev->sane.vendor = "CANON";
|
||||
dev->sane.model = CANON_get_device_name (&scan);
|
||||
dev->sane.type = "flatbed scanner";
|
||||
CANON_close_device (&scan);
|
||||
|
||||
++num_devices;
|
||||
dev->next = first_dev;
|
||||
first_dev = dev;
|
||||
|
||||
if (devp)
|
||||
*devp = dev;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
/* callback function for sanei_usb_attach_matching_devices */
|
||||
static SANE_Status
|
||||
attach_one (const char *name)
|
||||
{
|
||||
attach_scanner (name, 0);
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
/* Find our devices */
|
||||
SANE_Status
|
||||
sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
|
||||
{
|
||||
char config_line[PATH_MAX];
|
||||
size_t len;
|
||||
FILE *fp;
|
||||
|
||||
DBG_INIT ();
|
||||
|
||||
#if 0
|
||||
DBG_LEVEL = 10;
|
||||
#endif
|
||||
|
||||
DBG (2, "sane_init: version_code %s 0, authorize %s 0\n",
|
||||
version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!=");
|
||||
DBG (1, "sane_init: SANE Canon LiDE70 backend version %d.%d.%d from %s\n",
|
||||
V_MAJOR, V_MINOR, BUILD, PACKAGE_STRING);
|
||||
|
||||
if (version_code)
|
||||
*version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, BUILD);
|
||||
|
||||
sanei_usb_init ();
|
||||
|
||||
fp = sanei_config_open (CANONUSB_CONFIG_FILE);
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
/* no config-file: try these */
|
||||
attach_scanner ("/dev/scanner", 0);
|
||||
attach_scanner ("/dev/usbscanner", 0);
|
||||
attach_scanner ("/dev/usb/scanner", 0);
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
DBG (3, "reading configure file %s\n", CANONUSB_CONFIG_FILE);
|
||||
|
||||
while (sanei_config_read (config_line, sizeof (config_line), fp))
|
||||
{
|
||||
if (config_line[0] == '#')
|
||||
continue; /* ignore line comments */
|
||||
|
||||
len = strlen (config_line);
|
||||
|
||||
if (!len)
|
||||
continue; /* ignore empty lines */
|
||||
|
||||
DBG (4, "attach_matching_devices(%s)\n", config_line);
|
||||
sanei_usb_attach_matching_devices (config_line, attach_one);
|
||||
}
|
||||
|
||||
DBG (4, "finished reading configure file\n");
|
||||
|
||||
fclose (fp);
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sane_exit (void)
|
||||
{
|
||||
Canon_Device *dev, *next;
|
||||
|
||||
DBG (3, "sane_exit\n");
|
||||
|
||||
for (dev = first_dev; dev; dev = next)
|
||||
{
|
||||
next = dev->next;
|
||||
free (dev->name);
|
||||
free (dev);
|
||||
}
|
||||
|
||||
if (devlist)
|
||||
free (devlist);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
|
||||
{
|
||||
Canon_Device *dev;
|
||||
int i;
|
||||
|
||||
DBG (3, "sane_get_devices(local_only = %d)\n", local_only);
|
||||
|
||||
if (devlist)
|
||||
free (devlist);
|
||||
|
||||
devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
|
||||
if (!devlist)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
|
||||
i = 0;
|
||||
|
||||
for (dev = first_dev; i < num_devices; dev = dev->next)
|
||||
devlist[i++] = &dev->sane;
|
||||
|
||||
devlist[i++] = 0;
|
||||
|
||||
*device_list = devlist;
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
static SANE_Status
|
||||
init_options (CANON_Handle * chndl)
|
||||
{
|
||||
SANE_Option_Descriptor *od;
|
||||
|
||||
DBG (2, "begin init_options: chndl=%p\n", (void *) chndl);
|
||||
|
||||
/* opt_num_opts */
|
||||
od = &chndl->opt[opt_num_opts];
|
||||
od->name = "";
|
||||
od->title = SANE_TITLE_NUM_OPTIONS;
|
||||
od->desc = SANE_DESC_NUM_OPTIONS;
|
||||
od->type = SANE_TYPE_INT;
|
||||
od->unit = SANE_UNIT_NONE;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT;
|
||||
od->constraint_type = SANE_CONSTRAINT_NONE;
|
||||
od->constraint.range = 0;
|
||||
chndl->val[opt_num_opts].w = num_options;
|
||||
|
||||
DBG (2, "val[opt_num_opts]: %d\n", chndl->val[opt_num_opts].w);
|
||||
|
||||
/* opt_mode_group */
|
||||
od = &chndl->opt[opt_mode_group];
|
||||
od->name = "";
|
||||
od->title = SANE_I18N ("Scan Mode");
|
||||
od->desc = "";
|
||||
od->type = SANE_TYPE_GROUP;
|
||||
od->unit = SANE_UNIT_NONE;
|
||||
od->size = 0;
|
||||
od->cap = 0;
|
||||
od->constraint_type = SANE_CONSTRAINT_NONE;
|
||||
od->constraint.range = 0;
|
||||
chndl->val[opt_mode_group].w = 0;
|
||||
|
||||
/* opt_mode */
|
||||
od = &chndl->opt[opt_mode];
|
||||
od->name = SANE_NAME_SCAN_MODE;
|
||||
od->title = SANE_TITLE_SCAN_MODE;
|
||||
od->desc = SANE_DESC_SCAN_MODE;
|
||||
od->type = SANE_TYPE_STRING;
|
||||
od->unit = SANE_UNIT_NONE;
|
||||
od->size = max_string_size (mode_list);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
|
||||
od->constraint.string_list = mode_list;
|
||||
chndl->val[opt_mode].s = malloc (od->size);
|
||||
if (!chndl->val[opt_mode].s)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
strcpy (chndl->val[opt_mode].s, init_mode);
|
||||
chndl->graymode = init_graymode;
|
||||
|
||||
/* opt_threshold */
|
||||
od = &chndl->opt[opt_threshold];
|
||||
od->name = SANE_NAME_THRESHOLD;
|
||||
od->title = SANE_TITLE_THRESHOLD;
|
||||
od->desc = SANE_DESC_THRESHOLD;
|
||||
od->type = SANE_TYPE_INT;
|
||||
od->unit = SANE_UNIT_PERCENT;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE;
|
||||
od->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
od->constraint.range = &threshold_range;
|
||||
chndl->val[opt_threshold].w = init_threshold;
|
||||
|
||||
/* opt_resolution */
|
||||
od = &chndl->opt[opt_resolution];
|
||||
od->name = SANE_NAME_SCAN_RESOLUTION;
|
||||
od->title = SANE_TITLE_SCAN_RESOLUTION;
|
||||
od->desc = SANE_DESC_SCAN_RESOLUTION;
|
||||
od->type = SANE_TYPE_INT;
|
||||
od->unit = SANE_UNIT_DPI;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->constraint_type = SANE_CONSTRAINT_WORD_LIST;
|
||||
od->constraint.word_list = resolution_list;
|
||||
chndl->val[opt_resolution].w = init_resolution;
|
||||
|
||||
/* opt_non_blocking */
|
||||
od = &chndl->opt[opt_non_blocking];
|
||||
od->name = "non-blocking";
|
||||
od->title = SANE_I18N ("Use non-blocking IO");
|
||||
od->desc = SANE_I18N ("Use non-blocking IO for sane_read() if supported "
|
||||
"by the frontend.");
|
||||
od->type = SANE_TYPE_BOOL;
|
||||
od->unit = SANE_UNIT_NONE;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE;
|
||||
od->constraint_type = SANE_CONSTRAINT_NONE;
|
||||
od->constraint.range = 0;
|
||||
chndl->val[opt_non_blocking].w = init_non_blocking;
|
||||
|
||||
/* opt_geometry_group */
|
||||
od = &chndl->opt[opt_geometry_group];
|
||||
od->name = "";
|
||||
od->title = SANE_I18N ("Geometry");
|
||||
od->desc = "";
|
||||
od->type = SANE_TYPE_GROUP;
|
||||
od->unit = SANE_UNIT_NONE;
|
||||
od->size = 0;
|
||||
od->cap = 0;
|
||||
od->constraint_type = SANE_CONSTRAINT_NONE;
|
||||
od->constraint.range = 0;
|
||||
chndl->val[opt_geometry_group].w = 0;
|
||||
|
||||
/* opt_tl_x */
|
||||
od = &chndl->opt[opt_tl_x];
|
||||
od->name = SANE_NAME_SCAN_TL_X;
|
||||
od->title = SANE_TITLE_SCAN_TL_X;
|
||||
od->desc = SANE_DESC_SCAN_TL_X;
|
||||
od->type = SANE_TYPE_FIXED;
|
||||
od->unit = SANE_UNIT_MM;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
od->constraint.range = &widthRange;
|
||||
chndl->val[opt_tl_x].w = init_tl_x;
|
||||
|
||||
/* opt_tl_y */
|
||||
od = &chndl->opt[opt_tl_y];
|
||||
od->name = SANE_NAME_SCAN_TL_Y;
|
||||
od->title = SANE_TITLE_SCAN_TL_Y;
|
||||
od->desc = SANE_DESC_SCAN_TL_Y;
|
||||
od->type = SANE_TYPE_FIXED;
|
||||
od->unit = SANE_UNIT_MM;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
od->constraint.range = &heightRange;
|
||||
chndl->val[opt_tl_y].w = init_tl_y;
|
||||
|
||||
/* opt_br_x */
|
||||
od = &chndl->opt[opt_br_x];
|
||||
od->name = SANE_NAME_SCAN_BR_X;
|
||||
od->title = SANE_TITLE_SCAN_BR_X;
|
||||
od->desc = SANE_DESC_SCAN_BR_X;
|
||||
od->type = SANE_TYPE_FIXED;
|
||||
od->unit = SANE_UNIT_MM;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
od->constraint.range = &widthRange;
|
||||
chndl->val[opt_br_x].w = init_br_x;
|
||||
|
||||
/* opt_br_y */
|
||||
od = &chndl->opt[opt_br_y];
|
||||
od->name = SANE_NAME_SCAN_BR_Y;
|
||||
od->title = SANE_TITLE_SCAN_BR_Y;
|
||||
od->desc = SANE_DESC_SCAN_BR_Y;
|
||||
od->type = SANE_TYPE_FIXED;
|
||||
od->unit = SANE_UNIT_MM;
|
||||
od->size = sizeof (SANE_Word);
|
||||
od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
|
||||
od->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
od->constraint.range = &heightRange;
|
||||
chndl->val[opt_br_y].w = init_br_y;
|
||||
|
||||
DBG (2, "end init_options: chndl=%p\n", (void *) chndl);
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
sane_open (SANE_String_Const devicename, SANE_Handle * handle)
|
||||
{
|
||||
Canon_Device *dev;
|
||||
SANE_Status status;
|
||||
Canon_Scanner *scanner;
|
||||
|
||||
DBG (3, "sane_open\n");
|
||||
|
||||
if (devicename[0]) /* search for devicename */
|
||||
{
|
||||
DBG (4, "sane_open: devicename=%s\n", devicename);
|
||||
|
||||
for (dev = first_dev; dev; dev = dev->next)
|
||||
if (strcmp (dev->sane.name, devicename) == 0)
|
||||
break;
|
||||
|
||||
if (!dev)
|
||||
{
|
||||
status = attach_scanner (devicename, &dev);
|
||||
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG (2, "sane_open: no devicename, opening first device\n");
|
||||
dev = first_dev;
|
||||
}
|
||||
|
||||
if (!dev)
|
||||
return SANE_STATUS_INVAL;
|
||||
|
||||
scanner = malloc (sizeof (*scanner));
|
||||
|
||||
if (!scanner)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
|
||||
memset (scanner, 0, sizeof (*scanner));
|
||||
scanner->device = dev;
|
||||
|
||||
status = CANON_open_device (&scanner->scan, dev->sane.name);
|
||||
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
free (scanner);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = init_options (&scanner->scan);
|
||||
|
||||
*handle = scanner;
|
||||
|
||||
/* insert newly opened handle into list of open handles: */
|
||||
scanner->next = first_handle;
|
||||
|
||||
first_handle = scanner;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
print_options (CANON_Handle * chndl)
|
||||
{
|
||||
SANE_Option_Descriptor *od;
|
||||
SANE_Word option_number;
|
||||
SANE_Char caps[1024];
|
||||
|
||||
for (option_number = 0; option_number < num_options; option_number++)
|
||||
{
|
||||
od = &chndl->opt[option_number];
|
||||
DBG (50, "-----> number: %d\n", option_number);
|
||||
DBG (50, " name: `%s'\n", od->name);
|
||||
DBG (50, " title: `%s'\n", od->title);
|
||||
DBG (50, " description: `%s'\n", od->desc);
|
||||
DBG (50, " type: %s\n",
|
||||
od->type == SANE_TYPE_BOOL ? "SANE_TYPE_BOOL" :
|
||||
od->type == SANE_TYPE_INT ? "SANE_TYPE_INT" :
|
||||
od->type == SANE_TYPE_FIXED ? "SANE_TYPE_FIXED" :
|
||||
od->type == SANE_TYPE_STRING ? "SANE_TYPE_STRING" :
|
||||
od->type == SANE_TYPE_BUTTON ? "SANE_TYPE_BUTTON" :
|
||||
od->type == SANE_TYPE_GROUP ? "SANE_TYPE_GROUP" : "unknown");
|
||||
DBG (50, " unit: %s\n",
|
||||
od->unit == SANE_UNIT_NONE ? "SANE_UNIT_NONE" :
|
||||
od->unit == SANE_UNIT_PIXEL ? "SANE_UNIT_PIXEL" :
|
||||
od->unit == SANE_UNIT_BIT ? "SANE_UNIT_BIT" :
|
||||
od->unit == SANE_UNIT_MM ? "SANE_UNIT_MM" :
|
||||
od->unit == SANE_UNIT_DPI ? "SANE_UNIT_DPI" :
|
||||
od->unit == SANE_UNIT_PERCENT ? "SANE_UNIT_PERCENT" :
|
||||
od->unit == SANE_UNIT_MICROSECOND ? "SANE_UNIT_MICROSECOND" :
|
||||
"unknown");
|
||||
DBG (50, " size: %d\n", od->size);
|
||||
caps[0] = '\0';
|
||||
if (od->cap & SANE_CAP_SOFT_SELECT)
|
||||
strcat (caps, "SANE_CAP_SOFT_SELECT ");
|
||||
if (od->cap & SANE_CAP_HARD_SELECT)
|
||||
strcat (caps, "SANE_CAP_HARD_SELECT ");
|
||||
if (od->cap & SANE_CAP_SOFT_DETECT)
|
||||
strcat (caps, "SANE_CAP_SOFT_DETECT ");
|
||||
if (od->cap & SANE_CAP_EMULATED)
|
||||
strcat (caps, "SANE_CAP_EMULATED ");
|
||||
if (od->cap & SANE_CAP_AUTOMATIC)
|
||||
strcat (caps, "SANE_CAP_AUTOMATIC ");
|
||||
if (od->cap & SANE_CAP_INACTIVE)
|
||||
strcat (caps, "SANE_CAP_INACTIVE ");
|
||||
if (od->cap & SANE_CAP_ADVANCED)
|
||||
strcat (caps, "SANE_CAP_ADVANCED ");
|
||||
DBG (50, " capabilities: %s\n", caps);
|
||||
DBG (50, "constraint type: %s\n",
|
||||
od->constraint_type == SANE_CONSTRAINT_NONE ?
|
||||
"SANE_CONSTRAINT_NONE" :
|
||||
od->constraint_type == SANE_CONSTRAINT_RANGE ?
|
||||
"SANE_CONSTRAINT_RANGE" :
|
||||
od->constraint_type == SANE_CONSTRAINT_WORD_LIST ?
|
||||
"SANE_CONSTRAINT_WORD_LIST" :
|
||||
od->constraint_type == SANE_CONSTRAINT_STRING_LIST ?
|
||||
"SANE_CONSTRAINT_STRING_LIST" : "unknown");
|
||||
if (od->type == SANE_TYPE_INT)
|
||||
DBG (50, " value: %d\n", chndl->val[option_number].w);
|
||||
else if (od->type == SANE_TYPE_FIXED)
|
||||
DBG (50, " value: %f\n",
|
||||
SANE_UNFIX (chndl->val[option_number].w));
|
||||
else if (od->type == SANE_TYPE_STRING)
|
||||
DBG (50, " value: %s\n", chndl->val[option_number].s);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sane_close (SANE_Handle handle)
|
||||
{
|
||||
Canon_Scanner *prev, *scanner;
|
||||
SANE_Status res;
|
||||
|
||||
DBG (3, "sane_close\n");
|
||||
|
||||
scanner = handle;
|
||||
print_options (&scanner->scan);
|
||||
|
||||
if (!first_handle)
|
||||
{
|
||||
DBG (1, "ERROR: sane_close: no handles opened\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* remove handle from list of open handles: */
|
||||
|
||||
prev = NULL;
|
||||
|
||||
for (scanner = first_handle; scanner; scanner = scanner->next)
|
||||
{
|
||||
if (scanner == handle)
|
||||
break;
|
||||
|
||||
prev = scanner;
|
||||
}
|
||||
|
||||
if (!scanner)
|
||||
{
|
||||
DBG (1, "ERROR: sane_close: invalid handle %p\n", handle);
|
||||
return; /* oops, not a handle we know about */
|
||||
}
|
||||
|
||||
if (prev)
|
||||
prev->next = scanner->next;
|
||||
else
|
||||
first_handle = scanner->next;
|
||||
|
||||
res = CANON_close_device (&scanner->scan);
|
||||
DBG (3, "CANON_close_device returned: %d\n", res);
|
||||
free (scanner);
|
||||
}
|
||||
|
||||
const SANE_Option_Descriptor *
|
||||
sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
|
||||
{
|
||||
Canon_Scanner *scanner = handle;
|
||||
CANON_Handle *chndl = &scanner->scan;
|
||||
|
||||
|
||||
DBG (4, "sane_get_option_descriptor: handle=%p, option = %d\n",
|
||||
(void *) handle, option);
|
||||
if (option < 0 || option >= num_options)
|
||||
{
|
||||
DBG (3, "sane_get_option_descriptor: option < 0 || "
|
||||
"option > num_options\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return &chndl->opt[option];
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action,
|
||||
void *value, SANE_Int * info)
|
||||
{
|
||||
Canon_Scanner *scanner = handle;
|
||||
CANON_Handle *chndl = &scanner->scan;
|
||||
|
||||
SANE_Int myinfo = 0;
|
||||
SANE_Status status;
|
||||
|
||||
DBG (4, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n",
|
||||
(void *) handle, option, action, (void *) value, (void *) info);
|
||||
|
||||
if (option < 0 || option >= num_options)
|
||||
{
|
||||
DBG (1, "sane_control_option: option < 0 || option > num_options\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
if (!SANE_OPTION_IS_ACTIVE (chndl->opt[option].cap))
|
||||
{
|
||||
DBG (1, "sane_control_option: option is inactive\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
if (chndl->opt[option].type == SANE_TYPE_GROUP)
|
||||
{
|
||||
DBG (1, "sane_control_option: option is a group\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case SANE_ACTION_SET_VALUE:
|
||||
if (!SANE_OPTION_IS_SETTABLE (chndl->opt[option].cap))
|
||||
{
|
||||
DBG (1, "sane_control_option: option is not setable\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
status = sanei_constrain_value (&chndl->opt[option], value, &myinfo);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (3, "sane_control_option: sanei_constrain_value returned %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
switch (option)
|
||||
{
|
||||
case opt_tl_x: /* Fixed with parameter reloading */
|
||||
case opt_tl_y:
|
||||
case opt_br_x:
|
||||
case opt_br_y:
|
||||
if (chndl->val[option].w == *(SANE_Fixed *) value)
|
||||
{
|
||||
DBG (4, "sane_control_option: option %d (%s) not changed\n",
|
||||
option, chndl->opt[option].name);
|
||||
break;
|
||||
}
|
||||
chndl->val[option].w = *(SANE_Fixed *) value;
|
||||
myinfo |= SANE_INFO_RELOAD_PARAMS;
|
||||
DBG (4, "sane_control_option: set option %d (%s) to %.0f %s\n",
|
||||
option, chndl->opt[option].name,
|
||||
SANE_UNFIX (*(SANE_Fixed *) value),
|
||||
chndl->opt[option].unit == SANE_UNIT_MM ? "mm" : "dpi");
|
||||
break;
|
||||
case opt_non_blocking:
|
||||
if (chndl->val[option].w == *(SANE_Bool *) value)
|
||||
{
|
||||
DBG (4, "sane_control_option: option %d (%s) not changed\n",
|
||||
option, chndl->opt[option].name);
|
||||
break;
|
||||
}
|
||||
chndl->val[option].w = *(SANE_Bool *) value;
|
||||
DBG (4, "sane_control_option: set option %d (%s) to %s\n",
|
||||
option, chndl->opt[option].name,
|
||||
*(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
|
||||
break;
|
||||
case opt_resolution:
|
||||
case opt_threshold:
|
||||
if (chndl->val[option].w == *(SANE_Int *) value)
|
||||
{
|
||||
DBG (4, "sane_control_option: option %d (%s) not changed\n",
|
||||
option, chndl->opt[option].name);
|
||||
break;
|
||||
}
|
||||
chndl->val[option].w = *(SANE_Int *) value;
|
||||
myinfo |= SANE_INFO_RELOAD_PARAMS;
|
||||
myinfo |= SANE_INFO_RELOAD_OPTIONS;
|
||||
DBG (4, "sane_control_option: set option %d (%s) to %d\n",
|
||||
option, chndl->opt[option].name, *(SANE_Int *) value);
|
||||
break;
|
||||
case opt_mode:
|
||||
if (strcmp (chndl->val[option].s, value) == 0)
|
||||
{
|
||||
DBG (4, "sane_control_option: option %d (%s) not changed\n",
|
||||
option, chndl->opt[option].name);
|
||||
break;
|
||||
}
|
||||
strcpy (chndl->val[option].s, (SANE_String) value);
|
||||
|
||||
if (strcmp (chndl->val[option].s, SANE_VALUE_SCAN_MODE_LINEART) ==
|
||||
0)
|
||||
{
|
||||
chndl->opt[opt_threshold].cap &= ~SANE_CAP_INACTIVE;
|
||||
chndl->graymode = 2;
|
||||
}
|
||||
if (strcmp (chndl->val[option].s, SANE_VALUE_SCAN_MODE_COLOR) == 0)
|
||||
{
|
||||
chndl->opt[opt_threshold].cap |= SANE_CAP_INACTIVE;
|
||||
chndl->graymode = 0;
|
||||
}
|
||||
if (strcmp (chndl->val[option].s, SANE_VALUE_SCAN_MODE_GRAY) == 0)
|
||||
{
|
||||
chndl->opt[opt_threshold].cap |= SANE_CAP_INACTIVE;
|
||||
chndl->graymode = 1;
|
||||
}
|
||||
|
||||
|
||||
myinfo |= SANE_INFO_RELOAD_PARAMS;
|
||||
myinfo |= SANE_INFO_RELOAD_OPTIONS;
|
||||
DBG (4, "sane_control_option: set option %d (%s) to %s\n",
|
||||
option, chndl->opt[option].name, (SANE_String) value);
|
||||
break;
|
||||
default:
|
||||
DBG (1, "sane_control_option: trying to set unexpected option\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
case SANE_ACTION_GET_VALUE:
|
||||
switch (option)
|
||||
{
|
||||
case opt_num_opts:
|
||||
*(SANE_Word *) value = num_options;
|
||||
DBG (4, "sane_control_option: get option 0, value = %d\n",
|
||||
num_options);
|
||||
break;
|
||||
case opt_tl_x: /* Fixed options */
|
||||
case opt_tl_y:
|
||||
case opt_br_x:
|
||||
case opt_br_y:
|
||||
{
|
||||
*(SANE_Fixed *) value = chndl->val[option].w;
|
||||
DBG (4,
|
||||
"sane_control_option: get option %d (%s), value=%.1f %s\n",
|
||||
option, chndl->opt[option].name,
|
||||
SANE_UNFIX (*(SANE_Fixed *) value),
|
||||
chndl->opt[option].unit ==
|
||||
SANE_UNIT_MM ? "mm" : SANE_UNIT_DPI ? "dpi" : "");
|
||||
break;
|
||||
}
|
||||
case opt_non_blocking:
|
||||
*(SANE_Bool *) value = chndl->val[option].w;
|
||||
DBG (4,
|
||||
"sane_control_option: get option %d (%s), value=%s\n",
|
||||
option, chndl->opt[option].name,
|
||||
*(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
|
||||
break;
|
||||
case opt_mode: /* String (list) options */
|
||||
strcpy (value, chndl->val[option].s);
|
||||
DBG (4, "sane_control_option: get option %d (%s), value=`%s'\n",
|
||||
option, chndl->opt[option].name, (SANE_String) value);
|
||||
break;
|
||||
case opt_resolution:
|
||||
case opt_threshold:
|
||||
*(SANE_Int *) value = chndl->val[option].w;
|
||||
DBG (4, "sane_control_option: get option %d (%s), value=%d\n",
|
||||
option, chndl->opt[option].name, *(SANE_Int *) value);
|
||||
break;
|
||||
default:
|
||||
DBG (1, "sane_control_option: trying to get unexpected option\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DBG (1, "sane_control_option: trying unexpected action %d\n", action);
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
if (info)
|
||||
*info = myinfo;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
|
||||
{
|
||||
Canon_Scanner *hndl = handle; /* Eliminate compiler warning */
|
||||
CANON_Handle *chndl = &hndl->scan;
|
||||
|
||||
int rc = SANE_STATUS_GOOD;
|
||||
int w = SANE_UNFIX (chndl->val[opt_br_x].w -
|
||||
chndl->val[opt_tl_x].w) / MM_IN_INCH *
|
||||
chndl->val[opt_resolution].w;
|
||||
int h =
|
||||
SANE_UNFIX (chndl->val[opt_br_y].w -
|
||||
chndl->val[opt_tl_y].w) / MM_IN_INCH *
|
||||
chndl->val[opt_resolution].w;
|
||||
|
||||
DBG (3, "sane_get_parameters\n");
|
||||
chndl->params.depth = 8;
|
||||
chndl->params.last_frame = SANE_TRUE;
|
||||
chndl->params.pixels_per_line = w;
|
||||
chndl->params.lines = h;
|
||||
|
||||
if (chndl->graymode == 1)
|
||||
{
|
||||
chndl->params.format = SANE_FRAME_GRAY;
|
||||
chndl->params.bytes_per_line = w;
|
||||
}
|
||||
else if (chndl->graymode == 2)
|
||||
{
|
||||
chndl->params.format = SANE_FRAME_GRAY;
|
||||
w /= 8;
|
||||
|
||||
if ((chndl->params.pixels_per_line % 8) != 0)
|
||||
w++;
|
||||
|
||||
chndl->params.bytes_per_line = w;
|
||||
chndl->params.depth = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
chndl->params.format = SANE_FRAME_RGB;
|
||||
chndl->params.bytes_per_line = w * 3;
|
||||
}
|
||||
|
||||
*params = chndl->params;
|
||||
DBG (1, "%d\n", chndl->params.format);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
sane_start (SANE_Handle handle)
|
||||
{
|
||||
Canon_Scanner *scanner = handle;
|
||||
CANON_Handle *chndl = &scanner->scan;
|
||||
SANE_Status res;
|
||||
|
||||
DBG (3, "sane_start\n");
|
||||
|
||||
res = sane_get_parameters (handle, &chndl->params);
|
||||
res = CANON_set_scan_parameters (&scanner->scan);
|
||||
|
||||
if (res != SANE_STATUS_GOOD)
|
||||
return res;
|
||||
|
||||
return CANON_start_scan (&scanner->scan);
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
sane_read (SANE_Handle handle, SANE_Byte * data,
|
||||
SANE_Int max_length, SANE_Int * length)
|
||||
{
|
||||
Canon_Scanner *scanner = handle;
|
||||
return CANON_read (&scanner->scan, data, max_length, length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sane_cancel (SANE_Handle handle)
|
||||
{
|
||||
DBG (3, "sane_cancel: handle = %p\n", handle);
|
||||
DBG (3, "sane_cancel: cancelling is unsupported in this backend\n");
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
|
||||
{
|
||||
DBG (3, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle,
|
||||
non_blocking);
|
||||
if (non_blocking != SANE_FALSE)
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
SANE_Status
|
||||
sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
|
||||
{
|
||||
handle = handle; /* silence gcc */
|
||||
fd = fd; /* silence gcc */
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
# Options for the canon_lide70 backend
|
||||
|
||||
# Autodetect the Canon CanoScan LiDE 70
|
||||
usb 0x04a9 0x2225
|
||||
|
||||
# device list for non-linux-systems (enable if autodetect fails):
|
||||
#/dev/scanner
|
||||
#/dev/usb/scanner0
|
|
@ -19,6 +19,7 @@ bh
|
|||
canon
|
||||
canon630u
|
||||
canon_dr
|
||||
canon_lide70
|
||||
#canon_pp
|
||||
cardscan
|
||||
coolscan
|
||||
|
|
100
backend/dmc.c
100
backend/dmc.c
|
@ -512,59 +512,65 @@ DMCInitOptions(DMC_Camera *c)
|
|||
static SANE_Status
|
||||
DMCSetMode(DMC_Camera *c, int mode)
|
||||
{
|
||||
switch(mode) {
|
||||
switch (mode)
|
||||
{
|
||||
case IMAGE_MFI:
|
||||
c->tl_x_range.min = 0;
|
||||
c->tl_x_range.max = c->tl_x_range.max;
|
||||
c->tl_y_range.min = 0;
|
||||
c->tl_y_range.max = c->tl_y_range.max;
|
||||
c->br_x_range.min = 800;
|
||||
c->br_x_range.max = c->br_x_range.max;
|
||||
c->br_y_range.min = 599;
|
||||
c->br_y_range.max = c->br_y_range.max;
|
||||
break;
|
||||
c->tl_x_range.min = 0;
|
||||
c->tl_x_range.max = 800;
|
||||
c->tl_y_range.min = 0;
|
||||
c->tl_y_range.max = 599;
|
||||
c->br_x_range.min = c->tl_x_range.min;
|
||||
c->br_x_range.max = c->tl_x_range.max;
|
||||
c->br_y_range.min = c->tl_y_range.min;
|
||||
c->br_y_range.max = c->tl_y_range.max;
|
||||
break;
|
||||
|
||||
case IMAGE_VIEWFINDER:
|
||||
c->tl_x_range.min = 0;
|
||||
c->tl_x_range.max = c->tl_x_range.max;
|
||||
c->tl_y_range.min = 0;
|
||||
c->tl_y_range.max = c->tl_y_range.max;
|
||||
c->br_x_range.min = 269;
|
||||
c->br_x_range.max = c->br_x_range.max;
|
||||
c->br_y_range.min = 200;
|
||||
c->br_y_range.max = c->br_y_range.max;
|
||||
break;
|
||||
c->tl_x_range.min = 0;
|
||||
c->tl_x_range.max = 269;
|
||||
c->tl_y_range.min = 0;
|
||||
c->tl_y_range.max = 200;
|
||||
c->br_x_range.min = c->tl_x_range.min;
|
||||
c->br_x_range.max = c->tl_x_range.max;
|
||||
c->br_y_range.min = c->tl_y_range.min;
|
||||
c->br_y_range.max = c->tl_y_range.max;
|
||||
break;
|
||||
|
||||
case IMAGE_RAW:
|
||||
c->tl_x_range.min = 0;
|
||||
c->tl_x_range.max = c->tl_x_range.max;
|
||||
c->tl_y_range.min = 0;
|
||||
c->tl_y_range.max = c->tl_y_range.max;
|
||||
c->br_x_range.min = 1598;
|
||||
c->br_x_range.max = c->br_x_range.max;
|
||||
c->br_y_range.min = 599;
|
||||
c->br_y_range.max = c->br_y_range.max;
|
||||
break;
|
||||
c->tl_x_range.min = 0;
|
||||
c->tl_x_range.max = 1598;
|
||||
c->tl_y_range.min = 0;
|
||||
c->tl_y_range.max = 599;
|
||||
c->br_x_range.min = c->tl_x_range.min;
|
||||
c->br_x_range.max = c->tl_x_range.max;
|
||||
c->br_y_range.min = c->tl_y_range.min;
|
||||
c->br_y_range.max = c->tl_y_range.max;
|
||||
break;
|
||||
|
||||
case IMAGE_THUMB:
|
||||
c->tl_x_range.min = 0;
|
||||
c->tl_x_range.max = c->tl_x_range.max;
|
||||
c->tl_y_range.min = 0;
|
||||
c->tl_y_range.max = c->tl_y_range.max;
|
||||
c->br_x_range.min = 79;
|
||||
c->br_x_range.max = c->br_x_range.max;
|
||||
c->br_y_range.min = 59;
|
||||
c->br_y_range.max = c->br_y_range.max;
|
||||
break;
|
||||
c->tl_x_range.min = 0;
|
||||
c->tl_x_range.max = 79;
|
||||
c->tl_y_range.min = 0;
|
||||
c->tl_y_range.max = 59;
|
||||
c->br_x_range.min = c->tl_x_range.min;
|
||||
c->br_x_range.max = c->tl_x_range.max;
|
||||
c->br_y_range.min = c->tl_y_range.min;
|
||||
c->br_y_range.max = c->tl_y_range.max;
|
||||
break;
|
||||
|
||||
case IMAGE_SUPER_RES:
|
||||
c->tl_x_range.min = 0;
|
||||
c->tl_x_range.max = c->tl_x_range.max;
|
||||
c->tl_y_range.min = 0;
|
||||
c->tl_y_range.max = c->tl_y_range.max;
|
||||
c->br_x_range.min = 1598;
|
||||
c->br_x_range.max = c->br_x_range.max;
|
||||
c->br_y_range.min = 1199;
|
||||
c->br_y_range.max = c->br_y_range.max;
|
||||
break;
|
||||
c->tl_x_range.min = 0;
|
||||
c->tl_x_range.max = 1598;
|
||||
c->tl_y_range.min = 0;
|
||||
c->tl_y_range.max = 1199;
|
||||
c->br_x_range.min = c->tl_x_range.min;
|
||||
c->br_x_range.max = c->tl_x_range.max;
|
||||
c->br_y_range.min = c->tl_y_range.min;
|
||||
c->br_y_range.max = c->tl_y_range.max;
|
||||
break;
|
||||
|
||||
default:
|
||||
return SANE_STATUS_INVAL;
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
c->imageMode = mode;
|
||||
c->val[OPT_TL_X].w = c->tl_x_range.min;
|
||||
|
|
|
@ -47,6 +47,8 @@
|
|||
#ifdef HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sane/saneopts.h"
|
||||
|
|
|
@ -8,6 +8,12 @@
|
|||
# -> put your device ip instead of '123.456.789.10'.
|
||||
# -> put the port that you use instead of '88'.
|
||||
# For example, the lines below are for one device, but if you have several devices to use, you can duplicate the lines below as many times as you have devices.
|
||||
# You can also configure a device on a single line starting with 'device'
|
||||
# by writing a complete URL and an optional model name.
|
||||
|
||||
#device http://123.456.789.10:8080 OptionalModel1
|
||||
#device https://123.456.789.10:443 "Optional Model 2"
|
||||
#device unix:/run/proxy.sock:http://123.456.789.10:80
|
||||
|
||||
#[device]
|
||||
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -43,6 +43,7 @@
|
|||
#include "../include/sane/sane.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef BACKEND_NAME
|
||||
#define BACKEND_NAME escl
|
||||
|
@ -63,6 +64,14 @@
|
|||
|
||||
#define ESCL_CONFIG_FILE "escl.conf"
|
||||
|
||||
|
||||
enum {
|
||||
PLATEN = 0,
|
||||
ADFSIMPLEX,
|
||||
ADFDUPLEX
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
int p1_0;
|
||||
int p2_0;
|
||||
|
@ -82,9 +91,11 @@ typedef struct ESCL_Device {
|
|||
int port_nb;
|
||||
char *ip_address;
|
||||
char *type;
|
||||
SANE_Bool https;
|
||||
char *unix_socket;
|
||||
} ESCL_Device;
|
||||
|
||||
typedef struct capabilities
|
||||
typedef struct capst
|
||||
{
|
||||
int height;
|
||||
int width;
|
||||
|
@ -104,6 +115,7 @@ typedef struct capabilities
|
|||
int ContentTypesSize;
|
||||
SANE_String_Const *DocumentFormats;
|
||||
int DocumentFormatsSize;
|
||||
int format_ext;
|
||||
SANE_Int *SupportedResolutions;
|
||||
int SupportedResolutionsSize;
|
||||
SANE_String_Const *SupportedIntents;
|
||||
|
@ -114,11 +126,21 @@ typedef struct capabilities
|
|||
int RiskyRightMargin;
|
||||
int RiskyTopMargin;
|
||||
int RiskyBottomMargin;
|
||||
int duplex;
|
||||
} caps_t;
|
||||
|
||||
typedef struct capabilities
|
||||
{
|
||||
caps_t caps[3];
|
||||
int source;
|
||||
SANE_String_Const *Sources;
|
||||
int SourcesSize;
|
||||
FILE *tmp;
|
||||
unsigned char *img_data;
|
||||
long img_size;
|
||||
long img_read;
|
||||
int format_ext;
|
||||
size_t real_read;
|
||||
SANE_Bool work;
|
||||
} capabilities_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -148,24 +170,45 @@ enum
|
|||
OPT_TL_Y,
|
||||
OPT_BR_X,
|
||||
OPT_BR_Y,
|
||||
|
||||
OPT_SCAN_SOURCE,
|
||||
|
||||
NUM_OPTIONS
|
||||
};
|
||||
|
||||
#define PIXEL_TO_MM(pixels, dpi) SANE_FIX((double)pixels * 25.4 / (dpi))
|
||||
#define MM_TO_PIXEL(millimeters, dpi) (SANE_Word)round(SANE_UNFIX(millimeters) * (dpi) / 25.4)
|
||||
|
||||
ESCL_Device *escl_devices(SANE_Status *status);
|
||||
SANE_Status escl_device_add(int port_nb, const char *model_name, char *ip_address, char *type);
|
||||
SANE_Status escl_status(SANE_String_Const name);
|
||||
capabilities_t *escl_capabilities(SANE_String_Const name, SANE_Status *status);
|
||||
char *escl_newjob(capabilities_t *scanner, SANE_String_Const name, SANE_Status *status);
|
||||
SANE_Status escl_scan(capabilities_t *scanner, SANE_String_Const name, char *result);
|
||||
void escl_scanner(SANE_String_Const name, char *result);
|
||||
SANE_Status escl_device_add(int port_nb, const char *model_name,
|
||||
char *ip_address, char *type);
|
||||
SANE_Status escl_status(const ESCL_Device *device,
|
||||
int source,
|
||||
const char* jobId,
|
||||
SANE_Status *job);
|
||||
capabilities_t *escl_capabilities(const ESCL_Device *device, SANE_Status *status);
|
||||
char *escl_newjob(capabilities_t *scanner, const ESCL_Device *device,
|
||||
SANE_Status *status);
|
||||
SANE_Status escl_scan(capabilities_t *scanner, const ESCL_Device *device,
|
||||
char *result);
|
||||
void escl_scanner(const ESCL_Device *device, char *result);
|
||||
|
||||
typedef void CURL;
|
||||
void escl_curl_url(CURL *handle, const ESCL_Device *device, SANE_String_Const path);
|
||||
|
||||
unsigned char *escl_crop_surface(capabilities_t *scanner, unsigned char *surface,
|
||||
int w, int h, int bps, int *width, int *height);
|
||||
|
||||
// JPEG
|
||||
SANE_Status get_JPEG_data(capabilities_t *scanner, int *w, int *h, int *bps);
|
||||
SANE_Status get_JPEG_data(capabilities_t *scanner, int *width, int *height, int *bps);
|
||||
|
||||
// PNG
|
||||
SANE_Status get_PNG_data(capabilities_t *scanner, int *w, int *h, int *bps);
|
||||
SANE_Status get_PNG_data(capabilities_t *scanner, int *width, int *height, int *bps);
|
||||
|
||||
// TIFF
|
||||
SANE_Status get_TIFF_data(capabilities_t *scanner, int *w, int *h, int *bps);
|
||||
SANE_Status get_TIFF_data(capabilities_t *scanner, int *width, int *height, int *bps);
|
||||
|
||||
// PDF
|
||||
SANE_Status get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -45,7 +45,7 @@ struct cap
|
|||
* \fn static SANE_String_Const convert_elements(SANE_String_Const str)
|
||||
* \brief Function that converts the 'color modes' of the scanner (color/gray) to be understood by SANE.
|
||||
*
|
||||
* \return SANE_VALUE_SCAN_MODE_GRAY / SANE_VALUE_SCAN_MODE_COLOR ; NULL otherwise
|
||||
* \return SANE_VALUE_SCAN_MODE_GRAY / SANE_VALUE_SCAN_MODE_COLOR / SANE_VALUE_SCAN_MODE_LINEART; NULL otherwise
|
||||
*/
|
||||
static SANE_String_Const
|
||||
convert_elements(SANE_String_Const str)
|
||||
|
@ -54,6 +54,10 @@ convert_elements(SANE_String_Const str)
|
|||
return (SANE_VALUE_SCAN_MODE_GRAY);
|
||||
else if (strcmp(str, "RGB24") == 0)
|
||||
return (SANE_VALUE_SCAN_MODE_COLOR);
|
||||
#if(defined HAVE_POPPLER_GLIB)
|
||||
else if (strcmp(str, "BlackAndWhite1") == 0)
|
||||
return (SANE_VALUE_SCAN_MODE_LINEART);
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
@ -137,7 +141,7 @@ memory_callback_c(void *contents, size_t size, size_t nmemb, void *userp)
|
|||
|
||||
char *str = realloc(mem->memory, mem->size + realsize + 1);
|
||||
if (str == NULL) {
|
||||
fprintf(stderr, "not enough memory (realloc returned NULL)\n");
|
||||
DBG(10, "not enough memory (realloc returned NULL)\n");
|
||||
return (0);
|
||||
}
|
||||
mem->memory = str;
|
||||
|
@ -175,48 +179,61 @@ find_nodes_c(xmlNode *node)
|
|||
* \return 0
|
||||
*/
|
||||
static int
|
||||
find_valor_of_array_variables(xmlNode *node, capabilities_t *scanner)
|
||||
find_valor_of_array_variables(xmlNode *node, capabilities_t *scanner, int type)
|
||||
{
|
||||
const char *name = (const char *)node->name;
|
||||
if (strcmp(name, "ColorMode") == 0)
|
||||
scanner->ColorModes = char_to_array(scanner->ColorModes, &scanner->ColorModesSize, (SANE_String_Const)xmlNodeGetContent(node), 1);
|
||||
if (strcmp(name, "ColorMode") == 0) {
|
||||
const char *color = (SANE_String_Const)xmlNodeGetContent(node);
|
||||
if (type == PLATEN || strcmp(color, "BlackAndWhite1"))
|
||||
scanner->caps[type].ColorModes = char_to_array(scanner->caps[type].ColorModes, &scanner->caps[type].ColorModesSize, (SANE_String_Const)xmlNodeGetContent(node), 1);
|
||||
}
|
||||
else if (strcmp(name, "ContentType") == 0)
|
||||
scanner->ContentTypes = char_to_array(scanner->ContentTypes, &scanner->ContentTypesSize, (SANE_String_Const)xmlNodeGetContent(node), 0);
|
||||
scanner->caps[type].ContentTypes = char_to_array(scanner->caps[type].ContentTypes, &scanner->caps[type].ContentTypesSize, (SANE_String_Const)xmlNodeGetContent(node), 0);
|
||||
else if (strcmp(name, "DocumentFormat") == 0)
|
||||
{
|
||||
int i = 0;
|
||||
scanner->DocumentFormats = char_to_array(scanner->DocumentFormats, &scanner->DocumentFormatsSize, (SANE_String_Const)xmlNodeGetContent(node), 0);
|
||||
for(; i < scanner->DocumentFormatsSize; i++)
|
||||
SANE_Bool have_jpeg = SANE_FALSE, have_png = SANE_FALSE, have_tiff = SANE_FALSE, have_pdf = SANE_FALSE;
|
||||
scanner->caps[type].DocumentFormats = char_to_array(scanner->caps[type].DocumentFormats, &scanner->caps[type].DocumentFormatsSize, (SANE_String_Const)xmlNodeGetContent(node), 0);
|
||||
for(; i < scanner->caps[type].DocumentFormatsSize; i++)
|
||||
{
|
||||
if (scanner->default_format == NULL && !strcmp(scanner->DocumentFormats[i], "image/jpeg"))
|
||||
if (!strcmp(scanner->caps[type].DocumentFormats[i], "image/jpeg"))
|
||||
{
|
||||
scanner->default_format = strdup("image/jpeg");
|
||||
have_jpeg = SANE_TRUE;
|
||||
}
|
||||
#if(defined HAVE_LIBPNG)
|
||||
else if(!strcmp(scanner->DocumentFormats[i], "image/png") && (scanner->default_format == NULL || strcmp(scanner->default_format, "image/tiff")))
|
||||
else if(!strcmp(scanner->caps[type].DocumentFormats[i], "image/png"))
|
||||
{
|
||||
if (scanner->default_format)
|
||||
free(scanner->default_format);
|
||||
scanner->default_format = strdup("image/png");
|
||||
have_png = SANE_TRUE;
|
||||
}
|
||||
#endif
|
||||
#if(defined HAVE_TIFFIO_H)
|
||||
else if(!strcmp(scanner->DocumentFormats[i], "image/tiff"))
|
||||
else if(type == PLATEN && !strcmp(scanner->caps[type].DocumentFormats[i], "image/tiff"))
|
||||
{
|
||||
if (scanner->default_format)
|
||||
free(scanner->default_format);
|
||||
scanner->default_format = strdup("image/tiff");
|
||||
have_tiff = SANE_TRUE;
|
||||
}
|
||||
#endif
|
||||
#if(defined HAVE_POPPLER_GLIB)
|
||||
else if(type == PLATEN && !strcmp(scanner->caps[type].DocumentFormats[i], "application/pdf"))
|
||||
{
|
||||
have_pdf = SANE_TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
fprintf(stderr, "Capability : [%s]\n", scanner->default_format);
|
||||
if (have_pdf)
|
||||
scanner->caps[type].default_format = strdup("application/pdf");
|
||||
else if (have_tiff)
|
||||
scanner->caps[type].default_format = strdup("image/tiff");
|
||||
else if (have_png)
|
||||
scanner->caps[type].default_format = strdup("image/png");
|
||||
else if (have_jpeg)
|
||||
scanner->caps[type].default_format = strdup("image/jpeg");
|
||||
}
|
||||
else if (strcmp(name, "DocumentFormatExt") == 0)
|
||||
scanner->format_ext = 1;
|
||||
scanner->caps[type].format_ext = 1;
|
||||
else if (strcmp(name, "Intent") == 0)
|
||||
scanner->SupportedIntents = char_to_array(scanner->SupportedIntents, &scanner->SupportedIntentsSize, (SANE_String_Const)xmlNodeGetContent(node), 0);
|
||||
scanner->caps[type].SupportedIntents = char_to_array(scanner->caps[type].SupportedIntents, &scanner->caps[type].SupportedIntentsSize, (SANE_String_Const)xmlNodeGetContent(node), 0);
|
||||
else if (strcmp(name, "XResolution") == 0)
|
||||
scanner->SupportedResolutions = int_to_array(scanner->SupportedResolutions, &scanner->SupportedResolutionsSize, atoi((const char *)xmlNodeGetContent(node)));
|
||||
scanner->caps[type].SupportedResolutions = int_to_array(scanner->caps[type].SupportedResolutions, &scanner->caps[type].SupportedResolutionsSize, atoi((const char *)xmlNodeGetContent(node)));
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -230,39 +247,39 @@ find_valor_of_array_variables(xmlNode *node, capabilities_t *scanner)
|
|||
* \return 0
|
||||
*/
|
||||
static int
|
||||
find_value_of_int_variables(xmlNode *node, capabilities_t *scanner)
|
||||
find_value_of_int_variables(xmlNode *node, capabilities_t *scanner, int type)
|
||||
{
|
||||
int MaxWidth = 0;
|
||||
int MaxHeight = 0;
|
||||
const char *name = (const char *)node->name;
|
||||
|
||||
if (strcmp(name, "MinWidth") == 0)
|
||||
scanner->MinWidth = atoi((const char*)xmlNodeGetContent(node));
|
||||
scanner->caps[type].MinWidth = atoi((const char*)xmlNodeGetContent(node));
|
||||
else if (strcmp(name, "MaxWidth") == 0) {
|
||||
MaxWidth = atoi((const char*)xmlNodeGetContent(node));
|
||||
if (scanner->MaxWidth == 0 || MaxWidth < scanner->MaxWidth)
|
||||
scanner->MaxWidth = atoi((const char *)xmlNodeGetContent(node));
|
||||
if (scanner->caps[type].MaxWidth == 0 || MaxWidth < scanner->caps[type].MaxWidth)
|
||||
scanner->caps[type].MaxWidth = atoi((const char *)xmlNodeGetContent(node));
|
||||
}
|
||||
else if (strcmp(name, "MinHeight") == 0)
|
||||
scanner->MinHeight = atoi((const char*)xmlNodeGetContent(node));
|
||||
scanner->caps[type].MinHeight = atoi((const char*)xmlNodeGetContent(node));
|
||||
else if (strcmp(name, "MaxHeight") == 0) {
|
||||
MaxHeight = atoi((const char*)xmlNodeGetContent(node));
|
||||
if (scanner->MaxHeight == 0 || MaxHeight < scanner->MaxHeight)
|
||||
scanner->MaxHeight = atoi((const char *)xmlNodeGetContent(node));
|
||||
if (scanner->caps[type].MaxHeight == 0 || MaxHeight < scanner->caps[type].MaxHeight)
|
||||
scanner->caps[type].MaxHeight = atoi((const char *)xmlNodeGetContent(node));
|
||||
}
|
||||
else if (strcmp(name, "MaxScanRegions") == 0)
|
||||
scanner->MaxScanRegions = atoi((const char *)xmlNodeGetContent(node));
|
||||
scanner->caps[type].MaxScanRegions = atoi((const char *)xmlNodeGetContent(node));
|
||||
else if (strcmp(name, "MaxOpticalXResolution") == 0)
|
||||
scanner->MaxOpticalXResolution = atoi((const char *)xmlNodeGetContent(node));
|
||||
scanner->caps[type].MaxOpticalXResolution = atoi((const char *)xmlNodeGetContent(node));
|
||||
else if (strcmp(name, "RiskyLeftMargin") == 0)
|
||||
scanner->RiskyLeftMargin = atoi((const char *)xmlNodeGetContent(node));
|
||||
scanner->caps[type].RiskyLeftMargin = atoi((const char *)xmlNodeGetContent(node));
|
||||
else if (strcmp(name, "RiskyRightMargin") == 0)
|
||||
scanner->RiskyRightMargin = atoi((const char *)xmlNodeGetContent(node));
|
||||
scanner->caps[type].RiskyRightMargin = atoi((const char *)xmlNodeGetContent(node));
|
||||
else if (strcmp(name, "RiskyTopMargin") == 0)
|
||||
scanner->RiskyTopMargin = atoi((const char *)xmlNodeGetContent(node));
|
||||
scanner->caps[type].RiskyTopMargin = atoi((const char *)xmlNodeGetContent(node));
|
||||
else if (strcmp(name, "RiskyBottomMargin") == 0)
|
||||
scanner->RiskyBottomMargin = atoi((const char *)xmlNodeGetContent(node));
|
||||
find_valor_of_array_variables(node, scanner);
|
||||
scanner->caps[type].RiskyBottomMargin = atoi((const char *)xmlNodeGetContent(node));
|
||||
find_valor_of_array_variables(node, scanner, type);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -275,7 +292,7 @@ find_value_of_int_variables(xmlNode *node, capabilities_t *scanner)
|
|||
* \return 0
|
||||
*/
|
||||
static int
|
||||
find_true_variables(xmlNode *node, capabilities_t *scanner)
|
||||
find_true_variables(xmlNode *node, capabilities_t *scanner, int type)
|
||||
{
|
||||
const char *name = (const char *)node->name;
|
||||
if (strcmp(name, "MinWidth") == 0 ||
|
||||
|
@ -294,7 +311,7 @@ find_true_variables(xmlNode *node, capabilities_t *scanner)
|
|||
strcmp(name, "RiskyTopMargin") == 0 ||
|
||||
strcmp(name, "RiskyBottomMargin") == 0 ||
|
||||
strcmp(name, "DocumentFormatExt") == 0)
|
||||
find_value_of_int_variables(node, scanner);
|
||||
find_value_of_int_variables(node, scanner, type);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -305,21 +322,67 @@ find_true_variables(xmlNode *node, capabilities_t *scanner)
|
|||
* \return 0
|
||||
*/
|
||||
static int
|
||||
print_xml_c(xmlNode *node, capabilities_t *scanner)
|
||||
print_xml_c(xmlNode *node, capabilities_t *scanner, int type)
|
||||
{
|
||||
while (node) {
|
||||
if (node->type == XML_ELEMENT_NODE) {
|
||||
if (find_nodes_c(node))
|
||||
find_true_variables(node, scanner);
|
||||
if (find_nodes_c(node) && type != -1)
|
||||
find_true_variables(node, scanner, type);
|
||||
}
|
||||
print_xml_c(node->children, scanner);
|
||||
if (!strcmp((const char *)node->name, "PlatenInputCaps")) {
|
||||
scanner->Sources[PLATEN] = (SANE_String_Const)strdup(SANE_I18N ("Flatbed"));
|
||||
scanner->SourcesSize++;
|
||||
scanner->source = PLATEN;
|
||||
print_xml_c(node->children, scanner, PLATEN);
|
||||
scanner->caps[PLATEN].duplex = 0;
|
||||
}
|
||||
else if (!strcmp((const char *)node->name, "AdfSimplexInputCaps")) {
|
||||
scanner->Sources[ADFSIMPLEX] = (SANE_String_Const)strdup(SANE_I18N("ADF"));
|
||||
scanner->SourcesSize++;
|
||||
if (scanner->source == -1) scanner->source = ADFSIMPLEX;
|
||||
print_xml_c(node->children, scanner, ADFSIMPLEX);
|
||||
scanner->caps[ADFSIMPLEX].duplex = 0;
|
||||
}
|
||||
else if (!strcmp((const char *)node->name, "AdfDuplexInputCaps")) {
|
||||
scanner->Sources[ADFDUPLEX] = (SANE_String_Const)strdup(SANE_I18N ("ADF Duplex"));
|
||||
scanner->SourcesSize++;
|
||||
if (scanner->source == -1) scanner->source = ADFDUPLEX;
|
||||
print_xml_c(node->children, scanner, ADFDUPLEX);
|
||||
scanner->caps[ADFDUPLEX].duplex = 1;
|
||||
}
|
||||
else
|
||||
print_xml_c(node->children, scanner, type);
|
||||
node = node->next;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
_reduce_color_modes(capabilities_t *scanner)
|
||||
{
|
||||
int type = 0;
|
||||
for (type = 0; type < 3; type++) {
|
||||
if (scanner->caps[type].ColorModesSize) {
|
||||
if (scanner->caps[type].default_format &&
|
||||
strcmp(scanner->caps[type].default_format, "application/pdf")) {
|
||||
if (scanner->caps[type].ColorModesSize == 3) {
|
||||
free(scanner->caps[type].ColorModes);
|
||||
scanner->caps[type].ColorModes = NULL;
|
||||
scanner->caps[type].ColorModesSize = 0;
|
||||
scanner->caps[type].ColorModes = char_to_array(scanner->caps[type].ColorModes,
|
||||
&scanner->caps[type].ColorModesSize,
|
||||
(SANE_String_Const)SANE_VALUE_SCAN_MODE_GRAY, 0);
|
||||
scanner->caps[type].ColorModes = char_to_array(scanner->caps[type].ColorModes,
|
||||
&scanner->caps[type].ColorModesSize,
|
||||
(SANE_String_Const)SANE_VALUE_SCAN_MODE_COLOR, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn capabilities_t *escl_capabilities(SANE_String_Const name, SANE_Status *status)
|
||||
* \fn capabilities_t *escl_capabilities(const ESCL_Device *device, SANE_Status *status)
|
||||
* \brief Function that finally recovers all the capabilities of the scanner, using curl.
|
||||
* This function is called in the 'sane_open' function and it's the equivalent of
|
||||
* the following curl command : "curl http(s)://'ip':'port'/eSCL/ScannerCapabilities".
|
||||
|
@ -327,18 +390,18 @@ print_xml_c(xmlNode *node, capabilities_t *scanner)
|
|||
* \return scanner (the structure that stocks all the capabilities elements)
|
||||
*/
|
||||
capabilities_t *
|
||||
escl_capabilities(SANE_String_Const name, SANE_Status *status)
|
||||
escl_capabilities(const ESCL_Device *device, SANE_Status *status)
|
||||
{
|
||||
capabilities_t *scanner = (capabilities_t*)calloc(1, sizeof(capabilities_t));
|
||||
CURL *curl_handle = NULL;
|
||||
struct cap *var = NULL;
|
||||
xmlDoc *data = NULL;
|
||||
xmlNode *node = NULL;
|
||||
int i = 0;
|
||||
const char *scanner_capabilities = "/eSCL/ScannerCapabilities";
|
||||
char tmp[PATH_MAX] = { 0 };
|
||||
|
||||
*status = SANE_STATUS_GOOD;
|
||||
if (name == NULL)
|
||||
if (device == NULL)
|
||||
*status = SANE_STATUS_NO_MEM;
|
||||
var = (struct cap *)calloc(1, sizeof(struct cap));
|
||||
if (var == NULL)
|
||||
|
@ -346,32 +409,41 @@ escl_capabilities(SANE_String_Const name, SANE_Status *status)
|
|||
var->memory = malloc(1);
|
||||
var->size = 0;
|
||||
curl_handle = curl_easy_init();
|
||||
strcpy(tmp, name);
|
||||
strcat(tmp, scanner_capabilities);
|
||||
DBG( 1, "Get Capabilities : %s\n", tmp);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_URL, tmp);
|
||||
if (strncmp(name, "https", 5) == 0) {
|
||||
DBG( 1, "Ignoring safety certificates, use https\n");
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
}
|
||||
escl_curl_url(curl_handle, device, scanner_capabilities);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, memory_callback_c);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)var);
|
||||
if (curl_easy_perform(curl_handle) != CURLE_OK) {
|
||||
DBG( 1, "The scanner didn't respond.\n");
|
||||
CURLcode res = curl_easy_perform(curl_handle);
|
||||
if (res != CURLE_OK) {
|
||||
DBG( 1, "The scanner didn't respond: %s\n", curl_easy_strerror(res));
|
||||
*status = SANE_STATUS_INVAL;
|
||||
goto clean_data;
|
||||
}
|
||||
DBG( 10, "XML Capabilities[\n%s\n]\n", var->memory);
|
||||
data = xmlReadMemory(var->memory, var->size, "file.xml", NULL, 0);
|
||||
if (data == NULL)
|
||||
if (data == NULL) {
|
||||
*status = SANE_STATUS_NO_MEM;
|
||||
goto clean_data;
|
||||
}
|
||||
node = xmlDocGetRootElement(data);
|
||||
if (node == NULL)
|
||||
if (node == NULL) {
|
||||
*status = SANE_STATUS_NO_MEM;
|
||||
print_xml_c(node, scanner);
|
||||
goto clean;
|
||||
}
|
||||
|
||||
scanner->source = 0;
|
||||
scanner->Sources = (SANE_String_Const *)malloc(sizeof(SANE_String_Const) * 4);
|
||||
for (i = 0; i < 4; i++)
|
||||
scanner->Sources[i] = NULL;
|
||||
print_xml_c(node, scanner, -1);
|
||||
_reduce_color_modes(scanner);
|
||||
clean:
|
||||
xmlFreeDoc(data);
|
||||
clean_data:
|
||||
xmlCleanupParser();
|
||||
xmlMemoryDump();
|
||||
curl_easy_cleanup(curl_handle);
|
||||
free(var->memory);
|
||||
if (var)
|
||||
free(var->memory);
|
||||
free(var);
|
||||
return (scanner);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2020 Thierry HUCHARD <thierry@ordissimo.com>
|
||||
|
||||
This file is part of the SANE package.
|
||||
|
||||
SANE 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
SANE 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 sane; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
This file implements a SANE backend for eSCL scanners. */
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#include "escl.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
unsigned char *
|
||||
escl_crop_surface(capabilities_t *scanner,
|
||||
unsigned char *surface,
|
||||
int w,
|
||||
int h,
|
||||
int bps,
|
||||
int *width,
|
||||
int *height)
|
||||
{
|
||||
double ratio = 1.0;
|
||||
int x_off = 0, x = 0;
|
||||
int real_w = 0;
|
||||
int y_off = 0, y = 0;
|
||||
int real_h = 0;
|
||||
unsigned char *surface_crop = NULL;
|
||||
|
||||
DBG( 1, "Escl Image Crop\n");
|
||||
ratio = (double)w / (double)scanner->caps[scanner->source].width;
|
||||
scanner->caps[scanner->source].width = w;
|
||||
if (scanner->caps[scanner->source].pos_x < 0)
|
||||
scanner->caps[scanner->source].pos_x = 0;
|
||||
if (scanner->caps[scanner->source].pos_x &&
|
||||
(scanner->caps[scanner->source].width >
|
||||
scanner->caps[scanner->source].pos_x))
|
||||
x_off = (int)((double)scanner->caps[scanner->source].pos_x * ratio);
|
||||
real_w = scanner->caps[scanner->source].width - x_off;
|
||||
|
||||
scanner->caps[scanner->source].height = h;
|
||||
if (scanner->caps[scanner->source].pos_y &&
|
||||
(scanner->caps[scanner->source].height >
|
||||
scanner->caps[scanner->source].pos_y))
|
||||
y_off = (int)((double)scanner->caps[scanner->source].pos_y * ratio);
|
||||
real_h = scanner->caps[scanner->source].height - y_off;
|
||||
|
||||
DBG( 1, "Escl Image Crop [%dx%d|%dx%d]\n", scanner->caps[scanner->source].pos_x, scanner->caps[scanner->source].pos_y,
|
||||
scanner->caps[scanner->source].width, scanner->caps[scanner->source].height);
|
||||
|
||||
*width = real_w;
|
||||
*height = real_h;
|
||||
DBG( 1, "Escl Image Crop [%dx%d]\n", *width, *height);
|
||||
if (x_off > 0 || real_w < scanner->caps[scanner->source].width ||
|
||||
y_off > 0 || real_h < scanner->caps[scanner->source].height) {
|
||||
surface_crop = (unsigned char *)malloc (sizeof (unsigned char) * real_w
|
||||
* real_h * bps);
|
||||
if(!surface_crop) {
|
||||
DBG( 1, "Escl Crop : Surface_crop Memory allocation problem\n");
|
||||
free(surface);
|
||||
surface = NULL;
|
||||
goto finish;
|
||||
}
|
||||
for (y = 0; y < real_h; y++)
|
||||
{
|
||||
for (x = 0; x < real_w; x++)
|
||||
{
|
||||
surface_crop[(y * real_w * bps) + (x * bps)] =
|
||||
surface[((y + y_off) * w * bps) + ((x + x_off) * bps)];
|
||||
surface_crop[(y * real_w * bps) + (x * bps) + 1] =
|
||||
surface[((y + y_off) * w * bps) + ((x + x_off) * bps) + 1];
|
||||
surface_crop[(y * real_w * bps) + (x * bps) + 2] =
|
||||
surface[((y + y_off) * w * bps) + ((x + x_off) * bps) + 2];
|
||||
}
|
||||
}
|
||||
free(surface);
|
||||
surface = surface_crop;
|
||||
}
|
||||
// we don't need row pointers anymore
|
||||
scanner->img_data = surface;
|
||||
scanner->img_size = (int)(real_w * real_h * bps);
|
||||
scanner->img_read = 0;
|
||||
finish:
|
||||
return surface;
|
||||
}
|
|
@ -120,7 +120,6 @@ jpeg_RW_src(j_decompress_ptr cinfo, FILE *ctx)
|
|||
if (cinfo->src == NULL) {
|
||||
cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)
|
||||
((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(my_source_mgr));
|
||||
src = (my_source_mgr *) cinfo->src;
|
||||
}
|
||||
src = (my_source_mgr *) cinfo->src;
|
||||
src->pub.init_source = init_source;
|
||||
|
@ -154,7 +153,7 @@ output_no_message(j_common_ptr __sane_unused__ cinfo)
|
|||
* \return SANE_STATUS_GOOD (if everything is OK, otherwise, SANE_STATUS_NO_MEM/SANE_STATUS_INVAL)
|
||||
*/
|
||||
SANE_Status
|
||||
get_JPEG_data(capabilities_t *scanner, int *w, int *h, int *bps)
|
||||
get_JPEG_data(capabilities_t *scanner, int *width, int *height, int *bps)
|
||||
{
|
||||
int start = 0;
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
|
@ -162,6 +161,11 @@ get_JPEG_data(capabilities_t *scanner, int *w, int *h, int *bps)
|
|||
unsigned char *surface = NULL;
|
||||
struct my_error_mgr jerr;
|
||||
int lineSize = 0;
|
||||
JDIMENSION x_off = 0;
|
||||
JDIMENSION y_off = 0;
|
||||
JDIMENSION w = 0;
|
||||
JDIMENSION h = 0;
|
||||
int pos = 0;
|
||||
|
||||
if (scanner->tmp == NULL)
|
||||
return (SANE_STATUS_INVAL);
|
||||
|
@ -174,6 +178,7 @@ get_JPEG_data(capabilities_t *scanner, int *w, int *h, int *bps)
|
|||
jpeg_destroy_decompress(&cinfo);
|
||||
if (surface != NULL)
|
||||
free(surface);
|
||||
fseek(scanner->tmp, start, SEEK_SET);
|
||||
DBG( 1, "Escl Jpeg : Error reading jpeg\n");
|
||||
if (scanner->tmp) {
|
||||
fclose(scanner->tmp);
|
||||
|
@ -187,10 +192,42 @@ get_JPEG_data(capabilities_t *scanner, int *w, int *h, int *bps)
|
|||
cinfo.out_color_space = JCS_RGB;
|
||||
cinfo.quantize_colors = FALSE;
|
||||
jpeg_calc_output_dimensions(&cinfo);
|
||||
surface = malloc(cinfo.output_width * cinfo.output_height * cinfo.output_components);
|
||||
if (cinfo.output_width < (unsigned int)scanner->caps[scanner->source].width)
|
||||
scanner->caps[scanner->source].width = cinfo.output_width;
|
||||
if (scanner->caps[scanner->source].pos_x < 0)
|
||||
scanner->caps[scanner->source].pos_x = 0;
|
||||
|
||||
if (cinfo.output_height < (unsigned int)scanner->caps[scanner->source].height)
|
||||
scanner->caps[scanner->source].height = cinfo.output_height;
|
||||
if (scanner->caps[scanner->source].pos_y < 0)
|
||||
scanner->caps[scanner->source].pos_y = 0;
|
||||
DBG(10, "1-JPEF Geometry [%dx%d|%dx%d]\n",
|
||||
scanner->caps[scanner->source].pos_x,
|
||||
scanner->caps[scanner->source].pos_y,
|
||||
scanner->caps[scanner->source].width,
|
||||
scanner->caps[scanner->source].height);
|
||||
x_off = scanner->caps[scanner->source].pos_x;
|
||||
if (x_off > (unsigned int)scanner->caps[scanner->source].width) {
|
||||
w = scanner->caps[scanner->source].width;
|
||||
x_off = 0;
|
||||
}
|
||||
else
|
||||
w = scanner->caps[scanner->source].width - x_off;
|
||||
y_off = scanner->caps[scanner->source].pos_y;
|
||||
if(y_off > (unsigned int)scanner->caps[scanner->source].height) {
|
||||
h = scanner->caps[scanner->source].height;
|
||||
y_off = 0;
|
||||
}
|
||||
else
|
||||
h = scanner->caps[scanner->source].height - y_off;
|
||||
DBG(10, "2-JPEF Geometry [%dx%d|%dx%d]\n",
|
||||
x_off,
|
||||
y_off,
|
||||
w,
|
||||
h);
|
||||
surface = malloc(w * h * cinfo.output_components);
|
||||
if (surface == NULL) {
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fseek(scanner->tmp, start, SEEK_SET);
|
||||
DBG( 1, "Escl Jpeg : Memory allocation problem\n");
|
||||
if (scanner->tmp) {
|
||||
fclose(scanner->tmp);
|
||||
|
@ -198,17 +235,23 @@ get_JPEG_data(capabilities_t *scanner, int *w, int *h, int *bps)
|
|||
}
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
lineSize = cinfo.output_width * cinfo.output_components;
|
||||
jpeg_start_decompress(&cinfo);
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
rowptr[0] = (JSAMPROW)surface + (lineSize * cinfo.output_scanline);
|
||||
if (x_off > 0 || w < cinfo.output_width)
|
||||
jpeg_crop_scanline(&cinfo, &x_off, &w);
|
||||
lineSize = w * cinfo.output_components;
|
||||
if (y_off > 0)
|
||||
jpeg_skip_scanlines(&cinfo, y_off);
|
||||
pos = 0;
|
||||
while (cinfo.output_scanline < (unsigned int)scanner->caps[scanner->source].height) {
|
||||
rowptr[0] = (JSAMPROW)surface + (lineSize * pos); // ..cinfo.output_scanline);
|
||||
jpeg_read_scanlines(&cinfo, rowptr, (JDIMENSION) 1);
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
scanner->img_data = surface;
|
||||
scanner->img_size = lineSize * cinfo.output_height;
|
||||
scanner->img_size = lineSize * h;
|
||||
scanner->img_read = 0;
|
||||
*w = cinfo.output_width;
|
||||
*h = cinfo.output_height;
|
||||
*width = w;
|
||||
*height = h;
|
||||
*bps = cinfo.output_components;
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
@ -220,8 +263,8 @@ get_JPEG_data(capabilities_t *scanner, int *w, int *h, int *bps)
|
|||
|
||||
SANE_Status
|
||||
get_JPEG_data(capabilities_t __sane_unused__ *scanner,
|
||||
int __sane_unused__ *w,
|
||||
int __sane_unused__ *h,
|
||||
int __sane_unused__ *width,
|
||||
int __sane_unused__ *height,
|
||||
int __sane_unused__ *bps)
|
||||
{
|
||||
return (SANE_STATUS_INVAL);
|
||||
|
|
|
@ -0,0 +1,256 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2019 Thierry HUCHARD <thierry@ordissimo.com>
|
||||
|
||||
This file is part of the SANE package.
|
||||
|
||||
SANE 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
SANE 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 sane; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
This file implements a SANE backend for eSCL scanners. */
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#include "escl.h"
|
||||
|
||||
#include "../include/sane/sanei.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if(defined HAVE_MUPDF)
|
||||
#include <mupdf/fitz.h>
|
||||
#endif
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
|
||||
#if(defined HAVE_MUPDF)
|
||||
|
||||
// TODO: WIN32: HANDLE CreateFileW(), etc.
|
||||
// TODO: POSIX: int creat(), read(), write(), lseeko, etc.
|
||||
|
||||
typedef struct fz_file_stream_escl_s
|
||||
{
|
||||
FILE *file;
|
||||
unsigned char buffer[4096];
|
||||
} fz_file_stream_escl;
|
||||
|
||||
static int
|
||||
next_file_escl(fz_context *ctx, fz_stream *stm, size_t n)
|
||||
{
|
||||
fz_file_stream_escl *state = stm->state;
|
||||
|
||||
/* n is only a hint, that we can safely ignore */
|
||||
n = fread(state->buffer, 1, sizeof(state->buffer), state->file);
|
||||
if (n < sizeof(state->buffer) && ferror(state->file))
|
||||
fz_throw(ctx, FZ_ERROR_GENERIC, "read error: %s", strerror(errno));
|
||||
stm->rp = state->buffer;
|
||||
stm->wp = state->buffer + n;
|
||||
stm->pos += (int64_t)n;
|
||||
|
||||
if (n == 0)
|
||||
return EOF;
|
||||
return *stm->rp++;
|
||||
}
|
||||
|
||||
static void
|
||||
drop_file_escl(fz_context *ctx, void *state_)
|
||||
{
|
||||
fz_file_stream_escl *state = state_;
|
||||
int n = fclose(state->file);
|
||||
if (n < 0)
|
||||
fz_warn(ctx, "close error: %s", strerror(errno));
|
||||
fz_free(ctx, state);
|
||||
}
|
||||
|
||||
static void
|
||||
seek_file_escl(fz_context *ctx, fz_stream *stm, int64_t offset, int whence)
|
||||
{
|
||||
fz_file_stream_escl *state = stm->state;
|
||||
#ifdef _WIN32
|
||||
int64_t n = _fseeki64(state->file, offset, whence);
|
||||
#else
|
||||
int64_t n = fseeko(state->file, offset, whence);
|
||||
#endif
|
||||
if (n < 0)
|
||||
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot seek: %s", strerror(errno));
|
||||
#ifdef _WIN32
|
||||
stm->pos = _ftelli64(state->file);
|
||||
#else
|
||||
stm->pos = ftello(state->file);
|
||||
#endif
|
||||
stm->rp = state->buffer;
|
||||
stm->wp = state->buffer;
|
||||
}
|
||||
|
||||
static fz_stream *
|
||||
fz_open_file_ptr_escl(fz_context *ctx, FILE *file)
|
||||
{
|
||||
fz_stream *stm;
|
||||
fz_file_stream_escl *state = fz_malloc_struct(ctx, fz_file_stream_escl);
|
||||
state->file = file;
|
||||
|
||||
stm = fz_new_stream(ctx, state, next_file_escl, drop_file_escl);
|
||||
stm->seek = seek_file_escl;
|
||||
|
||||
return stm;
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn SANE_Status escl_sane_decompressor(escl_sane_t *handler)
|
||||
* \brief Function that aims to decompress the pdf image to SANE be able
|
||||
* to read the image.
|
||||
* This function is called in the "sane_read" function.
|
||||
*
|
||||
* \return SANE_STATUS_GOOD (if everything is OK, otherwise,
|
||||
* SANE_STATUS_NO_MEM/SANE_STATUS_INVAL)
|
||||
*/
|
||||
SANE_Status
|
||||
get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps)
|
||||
{
|
||||
int page_number = -1, page_count = -2;
|
||||
fz_context *ctx;
|
||||
fz_document *doc;
|
||||
fz_pixmap *pix;
|
||||
fz_matrix ctm;
|
||||
fz_stream *stream;
|
||||
unsigned char *surface = NULL; /* Image data */
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
|
||||
/* Create a context to hold the exception stack and various caches. */
|
||||
ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
|
||||
if (!ctx)
|
||||
{
|
||||
DBG(1, "cannot create mupdf context\n");
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto close_file;
|
||||
}
|
||||
|
||||
/* Register the default file types to handle. */
|
||||
fz_try(ctx)
|
||||
fz_register_document_handlers(ctx);
|
||||
fz_catch(ctx)
|
||||
{
|
||||
DBG(1, "cannot register document handlers: %s\n", fz_caught_message(ctx));
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto drop_context;
|
||||
}
|
||||
|
||||
/* Open the stream. */
|
||||
fz_try(ctx)
|
||||
stream = fz_open_file_ptr_escl(ctx, scanner->tmp);
|
||||
fz_catch(ctx)
|
||||
{
|
||||
DBG(1, "cannot open stream: %s\n", fz_caught_message(ctx));
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto drop_context;
|
||||
}
|
||||
|
||||
/* Seek stream. */
|
||||
fz_try(ctx)
|
||||
fz_seek(ctx, stream, 0, SEEK_SET);
|
||||
fz_catch(ctx)
|
||||
{
|
||||
DBG(1, "cannot seek stream: %s\n", fz_caught_message(ctx));
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto drop_stream;
|
||||
}
|
||||
|
||||
/* Open the document. */
|
||||
fz_try(ctx)
|
||||
doc = fz_open_document_with_stream(ctx, "filename.pdf", stream);
|
||||
fz_catch(ctx)
|
||||
{
|
||||
DBG(1, "cannot open document: %s\n", fz_caught_message(ctx));
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto drop_stream;
|
||||
}
|
||||
|
||||
/* Count the number of pages. */
|
||||
fz_try(ctx)
|
||||
page_count = fz_count_pages(ctx, doc);
|
||||
fz_catch(ctx)
|
||||
{
|
||||
DBG(1, "cannot count number of pages: %s\n", fz_caught_message(ctx));
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto drop_document;
|
||||
}
|
||||
|
||||
if (page_number < 0 || page_number >= page_count)
|
||||
{
|
||||
DBG(1, "page number out of range: %d (page count %d)\n", page_number + 1, page_count);
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto drop_document;
|
||||
}
|
||||
|
||||
/* Compute a transformation matrix for the zoom and rotation desired. */
|
||||
/* The default resolution without scaling is 72 dpi. */
|
||||
fz_scale(&ctm, (float)1.0, (float)1.0);
|
||||
fz_pre_rotate(&ctm, (float)0.0);
|
||||
|
||||
/* Render page to an RGB pixmap. */
|
||||
fz_try(ctx)
|
||||
pix = fz_new_pixmap_from_page_number(ctx, doc, 0, &ctm, fz_device_rgb(ctx), 0);
|
||||
fz_catch(ctx)
|
||||
{
|
||||
DBG(1, "cannot render page: %s\n", fz_caught_message(ctx));
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto drop_document;
|
||||
}
|
||||
|
||||
surface = malloc(pix->h * pix->stride);
|
||||
memcpy(surface, pix->samples, (pix->h * pix->stride));
|
||||
|
||||
// If necessary, trim the image.
|
||||
surface = escl_crop_surface(scanner, surface, pix->w, pix->h, pix->n, width, height);
|
||||
if (!surface) {
|
||||
DBG( 1, "Escl Pdf : Surface Memory allocation problem\n");
|
||||
status = SANE_STATUS_NO_MEM;
|
||||
goto drop_pix;
|
||||
}
|
||||
*bps = pix->n;
|
||||
|
||||
/* Clean up. */
|
||||
drop_pix:
|
||||
fz_drop_pixmap(ctx, pix);
|
||||
drop_document:
|
||||
fz_drop_document(ctx, doc);
|
||||
drop_stream:
|
||||
fz_drop_stream(ctx, stream);
|
||||
drop_context:
|
||||
fz_drop_context(ctx);
|
||||
|
||||
close_file:
|
||||
if (scanner->tmp)
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
return status;
|
||||
}
|
||||
#else
|
||||
|
||||
SANE_Status
|
||||
get_PDF_data(capabilities_t __sane_unused__ *scanner,
|
||||
int __sane_unused__ *width,
|
||||
int __sane_unused__ *height,
|
||||
int __sane_unused__ *bps)
|
||||
{
|
||||
return (SANE_STATUS_INVAL);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -68,18 +68,11 @@ static const char settings[] =
|
|||
" <scan:ColorMode>%s</scan:ColorMode>" \
|
||||
" <scan:XResolution>%d</scan:XResolution>" \
|
||||
" <scan:YResolution>%d</scan:YResolution>" \
|
||||
" <pwg:InputSource>Platen</pwg:InputSource>" \
|
||||
" <pwg:InputSource>%s</pwg:InputSource>" \
|
||||
" <scan:InputSource>%s</scan:InputSource>" \
|
||||
"%s" \
|
||||
"</scan:ScanSettings>";
|
||||
|
||||
static char formatExtJPEG[] =
|
||||
" <scan:DocumentFormatExt>image/jpeg</scan:DocumentFormatExt>";
|
||||
|
||||
static char formatExtPNG[] =
|
||||
" <scan:DocumentFormatExt>image/png</scan:DocumentFormatExt>";
|
||||
|
||||
static char formatExtTIFF[] =
|
||||
" <scan:DocumentFormatExt>image/tiff</scan:DocumentFormatExt>";
|
||||
|
||||
/**
|
||||
* \fn static size_t download_callback(void *str, size_t size, size_t nmemb, void *userp)
|
||||
* \brief Callback function that stocks in memory the content of the 'job'. Example below :
|
||||
|
@ -122,7 +115,7 @@ download_callback(void *str, size_t size, size_t nmemb, void *userp)
|
|||
}
|
||||
|
||||
/**
|
||||
* \fn char *escl_newjob (capabilities_t *scanner, SANE_String_Const name, SANE_Status *status)
|
||||
* \fn char *escl_newjob (capabilities_t *scanner, const ESCL_Device *device, SANE_Status *status)
|
||||
* \brief Function that, using curl, uploads the data (composed by the scanner capabilities) to the
|
||||
* server to download the 'job' and recover the 'new job' (char *result), in LOCATION.
|
||||
* This function is called in the 'sane_start' function and it's the equivalent of the
|
||||
|
@ -131,22 +124,23 @@ download_callback(void *str, size_t size, size_t nmemb, void *userp)
|
|||
* \return result (the 'new job', situated in LOCATION)
|
||||
*/
|
||||
char *
|
||||
escl_newjob (capabilities_t *scanner, SANE_String_Const name, SANE_Status *status)
|
||||
escl_newjob (capabilities_t *scanner, const ESCL_Device *device, SANE_Status *status)
|
||||
{
|
||||
CURL *curl_handle = NULL;
|
||||
int off_x = 0, off_y = 0;
|
||||
struct uploading *upload = NULL;
|
||||
struct downloading *download = NULL;
|
||||
const char *scan_jobs = "/eSCL/ScanJobs";
|
||||
char cap_data[PATH_MAX] = { 0 };
|
||||
char job_cmd[PATH_MAX] = { 0 };
|
||||
char *location = NULL;
|
||||
char *result = NULL;
|
||||
char *temporary = NULL;
|
||||
char *f_ext = "";
|
||||
char *format_ext = NULL;
|
||||
char duplex_mode[1024] = { 0 };
|
||||
|
||||
*status = SANE_STATUS_GOOD;
|
||||
if (name == NULL || scanner == NULL) {
|
||||
if (device == NULL || scanner == NULL) {
|
||||
*status = SANE_STATUS_NO_MEM;
|
||||
DBG( 1, "Create NewJob : the name or the scan are invalid.\n");
|
||||
return (NULL);
|
||||
|
@ -165,64 +159,89 @@ escl_newjob (capabilities_t *scanner, SANE_String_Const name, SANE_Status *statu
|
|||
return (NULL);
|
||||
}
|
||||
curl_handle = curl_easy_init();
|
||||
if (scanner->format_ext == 1)
|
||||
if (scanner->caps[scanner->source].format_ext == 1)
|
||||
{
|
||||
if (!strcmp(scanner->default_format, "image/jpeg"))
|
||||
format_ext = formatExtJPEG;
|
||||
else if (!strcmp(scanner->default_format, "image/png"))
|
||||
format_ext = formatExtPNG;
|
||||
else if (!strcmp(scanner->default_format, "image/tiff"))
|
||||
format_ext = formatExtTIFF;
|
||||
else
|
||||
format_ext = f_ext;
|
||||
char f_ext_tmp[1024];
|
||||
snprintf(f_ext_tmp, sizeof(f_ext_tmp),
|
||||
" <scan:DocumentFormatExt>%s</scan:DocumentFormatExt>",
|
||||
scanner->caps[scanner->source].default_format);
|
||||
format_ext = f_ext_tmp;
|
||||
}
|
||||
else
|
||||
format_ext = f_ext;
|
||||
DBG( 1, "Create NewJob : %s\n", scanner->default_format);
|
||||
if(scanner->source > PLATEN && scanner->Sources[ADFDUPLEX]) {
|
||||
snprintf(duplex_mode, sizeof(duplex_mode),
|
||||
" <scan:Duplex>%s</scan:Duplex>",
|
||||
scanner->source == ADFDUPLEX ? "true" : "false");
|
||||
}
|
||||
DBG( 1, "Create NewJob : %s\n", scanner->caps[scanner->source].default_format);
|
||||
if (scanner->caps[scanner->source].pos_x > scanner->caps[scanner->source].width)
|
||||
off_x = (scanner->caps[scanner->source].pos_x > scanner->caps[scanner->source].width) / 2;
|
||||
if (scanner->caps[scanner->source].pos_y > scanner->caps[scanner->source].height)
|
||||
off_y = (scanner->caps[scanner->source].pos_y > scanner->caps[scanner->source].height) / 2;
|
||||
if (curl_handle != NULL) {
|
||||
snprintf(cap_data, sizeof(cap_data), settings, scanner->height, scanner->width, 0, 0, scanner->default_format,
|
||||
format_ext,
|
||||
scanner->default_color, scanner->default_resolution, scanner->default_resolution);
|
||||
char *source = (scanner->source == PLATEN ? "Platen" : "Feeder");
|
||||
snprintf(cap_data, sizeof(cap_data), settings,
|
||||
scanner->caps[scanner->source].height,
|
||||
scanner->caps[scanner->source].width,
|
||||
off_x,
|
||||
off_y,
|
||||
scanner->caps[scanner->source].default_format,
|
||||
format_ext,
|
||||
scanner->caps[scanner->source].default_color,
|
||||
scanner->caps[scanner->source].default_resolution,
|
||||
scanner->caps[scanner->source].default_resolution,
|
||||
source,
|
||||
source,
|
||||
duplex_mode[0] == 0 ? "" : duplex_mode);
|
||||
DBG( 1, "Create NewJob : %s\n", cap_data);
|
||||
upload->read_data = strdup(cap_data);
|
||||
upload->size = strlen(cap_data);
|
||||
download->memory = malloc(1);
|
||||
download->size = 0;
|
||||
strcpy(job_cmd, name);
|
||||
strcat(job_cmd, scan_jobs);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_URL, job_cmd);
|
||||
if (strncmp(name, "https", 5) == 0) {
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
}
|
||||
escl_curl_url(curl_handle, device, scan_jobs);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, upload->read_data);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, upload->size);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, download_callback);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, (void *)download);
|
||||
if (curl_easy_perform(curl_handle) != CURLE_OK) {
|
||||
DBG( 1, "Create NewJob : the scanner responded incorrectly.\n");
|
||||
CURLcode res = curl_easy_perform(curl_handle);
|
||||
if (res != CURLE_OK) {
|
||||
DBG( 1, "Create NewJob : the scanner responded incorrectly: %s\n", curl_easy_strerror(res));
|
||||
*status = SANE_STATUS_INVAL;
|
||||
}
|
||||
else {
|
||||
if (download->memory != NULL) {
|
||||
if (strstr(download->memory, "Location:")) {
|
||||
temporary = strrchr(download->memory, '/');
|
||||
char *tmp_location = strstr(download->memory, "Location:");
|
||||
if (tmp_location) {
|
||||
temporary = strchr(tmp_location, '\r');
|
||||
if (temporary == NULL)
|
||||
temporary = strchr(tmp_location, '\n');
|
||||
if (temporary != NULL) {
|
||||
location = strchr(temporary, '\r');
|
||||
if (location == NULL)
|
||||
location = strchr(temporary, '\n');
|
||||
else {
|
||||
*location = '\0';
|
||||
result = strdup(temporary);
|
||||
}
|
||||
DBG( 1, "Create NewJob : %s\n", result);
|
||||
*temporary = '\0';
|
||||
location = strrchr(tmp_location,'/');
|
||||
if (location) {
|
||||
result = strdup(location);
|
||||
DBG( 1, "Create NewJob : %s\n", result);
|
||||
*temporary = '\n';
|
||||
}
|
||||
}
|
||||
if (result == NULL) {
|
||||
DBG( 1, "Error : Create NewJob, no location: %s\n", download->memory);
|
||||
*status = SANE_STATUS_INVAL;
|
||||
}
|
||||
free(download->memory);
|
||||
}
|
||||
else {
|
||||
DBG( 1, "Create NewJob : The creation of the failed job\n");
|
||||
*status = SANE_STATUS_INVAL;
|
||||
DBG( 1, "Create NewJob : The creation of the failed job: %s\n", download->memory);
|
||||
// If "409 Conflict" appear it means that there is no paper in feeder
|
||||
if (strstr(download->memory, "409 Conflict") != NULL)
|
||||
*status = SANE_STATUS_NO_DOCS;
|
||||
// If "503 Service Unavailable" appear, it means that device is busy (scanning in progress)
|
||||
else if (strstr(download->memory, "503 Service Unavailable") != NULL)
|
||||
*status = SANE_STATUS_DEVICE_BUSY;
|
||||
else
|
||||
*status = SANE_STATUS_INVAL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -0,0 +1,223 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2019 Thierry HUCHARD <thierry@ordissimo.com>
|
||||
|
||||
This file is part of the SANE package.
|
||||
|
||||
SANE 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
SANE 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 sane; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
This file implements a SANE backend for eSCL scanners. */
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#include "escl.h"
|
||||
|
||||
#include "../include/sane/sanei.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if(defined HAVE_POPPLER_GLIB)
|
||||
#include <poppler/glib/poppler.h>
|
||||
#endif
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
|
||||
#if(defined HAVE_POPPLER_GLIB)
|
||||
|
||||
#define INPUT_BUFFER_SIZE 4096
|
||||
|
||||
static unsigned char*
|
||||
set_file_in_buffer(FILE *fp, int *size)
|
||||
{
|
||||
char buffer[1024] = { 0 };
|
||||
unsigned char *data = (unsigned char *)calloc(1, sizeof(char));
|
||||
int nx = 0;
|
||||
|
||||
while(!feof(fp))
|
||||
{
|
||||
int n = fread(buffer,sizeof(char),1024,fp);
|
||||
unsigned char *t = realloc(data, nx + n + 1);
|
||||
if (t == NULL) {
|
||||
DBG(10, "not enough memory (realloc returned NULL)");
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
data = t;
|
||||
memcpy(&(data[nx]), buffer, n);
|
||||
nx = nx + n;
|
||||
data[nx] = 0;
|
||||
}
|
||||
*size = nx;
|
||||
return data;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
cairo_surface_to_pixels (cairo_surface_t *surface, int bps)
|
||||
{
|
||||
int cairo_width, cairo_height, cairo_rowstride;
|
||||
unsigned char *data, *dst, *cairo_data;
|
||||
unsigned int *src;
|
||||
int x, y;
|
||||
|
||||
cairo_width = cairo_image_surface_get_width (surface);
|
||||
cairo_height = cairo_image_surface_get_height (surface);
|
||||
cairo_rowstride = cairo_image_surface_get_stride (surface);
|
||||
cairo_data = cairo_image_surface_get_data (surface);
|
||||
data = (unsigned char*)calloc(1, sizeof(unsigned char) * (cairo_height * cairo_width * bps));
|
||||
|
||||
for (y = 0; y < cairo_height; y++)
|
||||
{
|
||||
src = (unsigned int *) (cairo_data + y * cairo_rowstride);
|
||||
dst = data + y * (cairo_width * bps);
|
||||
for (x = 0; x < cairo_width; x++)
|
||||
{
|
||||
dst[0] = (*src >> 16) & 0xff;
|
||||
dst[1] = (*src >> 8) & 0xff;
|
||||
dst[2] = (*src >> 0) & 0xff;
|
||||
dst += bps;
|
||||
src++;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
SANE_Status
|
||||
get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps)
|
||||
{
|
||||
cairo_surface_t *cairo_surface = NULL;
|
||||
cairo_t *cr;
|
||||
PopplerPage *page;
|
||||
PopplerDocument *doc;
|
||||
double dw, dh;
|
||||
int w, h, size = 0;
|
||||
char *data = NULL;
|
||||
unsigned char* surface = NULL;
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
|
||||
|
||||
data = (char*)set_file_in_buffer(scanner->tmp, &size);
|
||||
if (!data) {
|
||||
DBG(1, "Error : poppler_document_new_from_data");
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto close_file;
|
||||
}
|
||||
doc = poppler_document_new_from_data(data,
|
||||
size,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (!doc) {
|
||||
DBG(1, "Error : poppler_document_new_from_data");
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto free_file;
|
||||
}
|
||||
|
||||
page = poppler_document_get_page (doc, 0);
|
||||
if (!page) {
|
||||
DBG(1, "Error : poppler_document_get_page");
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto free_doc;
|
||||
}
|
||||
|
||||
poppler_page_get_size (page, &dw, &dh);
|
||||
dw = (double)scanner->caps[scanner->source].default_resolution * dw / 72.0;
|
||||
dh = (double)scanner->caps[scanner->source].default_resolution * dh / 72.0;
|
||||
w = (int)ceil(dw);
|
||||
h = (int)ceil(dh);
|
||||
cairo_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h);
|
||||
if (!cairo_surface) {
|
||||
DBG(1, "Error : cairo_image_surface_create");
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto free_page;
|
||||
}
|
||||
|
||||
cr = cairo_create (cairo_surface);
|
||||
if (!cairo_surface) {
|
||||
DBG(1, "Error : cairo_create");
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto free_surface;
|
||||
}
|
||||
cairo_scale (cr, (double)scanner->caps[scanner->source].default_resolution / 72.0,
|
||||
(double)scanner->caps[scanner->source].default_resolution / 72.0);
|
||||
cairo_save (cr);
|
||||
poppler_page_render (page, cr);
|
||||
cairo_restore (cr);
|
||||
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER);
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_paint (cr);
|
||||
|
||||
int st = cairo_status(cr);
|
||||
if (st)
|
||||
{
|
||||
DBG(1, "%s", cairo_status_to_string (st));
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto destroy_cr;
|
||||
}
|
||||
|
||||
*bps = 3;
|
||||
|
||||
DBG(1, "Escl Pdf : Image Size [%dx%d]\n", w, h);
|
||||
|
||||
surface = cairo_surface_to_pixels (cairo_surface, *bps);
|
||||
if (!surface) {
|
||||
status = SANE_STATUS_NO_MEM;
|
||||
DBG(1, "Escl Pdf : Surface Memory allocation problem");
|
||||
goto destroy_cr;
|
||||
}
|
||||
|
||||
// If necessary, trim the image.
|
||||
surface = escl_crop_surface(scanner, surface, w, h, *bps, width, height);
|
||||
if (!surface) {
|
||||
DBG(1, "Escl Pdf Crop: Surface Memory allocation problem");
|
||||
status = SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
destroy_cr:
|
||||
cairo_destroy (cr);
|
||||
free_surface:
|
||||
cairo_surface_destroy (cairo_surface);
|
||||
free_page:
|
||||
g_object_unref (page);
|
||||
free_doc:
|
||||
g_object_unref (doc);
|
||||
free_file:
|
||||
free(data);
|
||||
close_file:
|
||||
if (scanner->tmp)
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
return status;
|
||||
}
|
||||
#else
|
||||
|
||||
SANE_Status
|
||||
get_PDF_data(capabilities_t __sane_unused__ *scanner,
|
||||
int __sane_unused__ *width,
|
||||
int __sane_unused__ *height,
|
||||
int __sane_unused__ *bps)
|
||||
{
|
||||
return (SANE_STATUS_INVAL);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -49,14 +49,15 @@
|
|||
* \return SANE_STATUS_GOOD (if everything is OK, otherwise, SANE_STATUS_NO_MEM/SANE_STATUS_INVAL)
|
||||
*/
|
||||
SANE_Status
|
||||
get_PNG_data(capabilities_t *scanner, int *w, int *h, int *components)
|
||||
get_PNG_data(capabilities_t *scanner, int *width, int *height, int *bps)
|
||||
{
|
||||
unsigned int width = 0; /* largeur */
|
||||
unsigned int height = 0; /* hauteur */
|
||||
int bps = 3; /* composantes d'un texel */
|
||||
unsigned char *texels = NULL; /* données de l'image */
|
||||
unsigned int w = 0;
|
||||
unsigned int h = 0;
|
||||
int components = 3;
|
||||
unsigned char *surface = NULL; /* Image data */
|
||||
unsigned int i = 0;
|
||||
png_byte magic[8];
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
|
||||
// read magic number
|
||||
fread (magic, 1, sizeof (magic), scanner->tmp);
|
||||
|
@ -64,11 +65,8 @@ get_PNG_data(capabilities_t *scanner, int *w, int *h, int *components)
|
|||
if (!png_check_sig (magic, sizeof (magic)))
|
||||
{
|
||||
DBG( 1, "Escl Png : PNG error is not a valid PNG image!\n");
|
||||
if (scanner->tmp) {
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
}
|
||||
return (SANE_STATUS_INVAL);
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto close_file;
|
||||
}
|
||||
// create a png read struct
|
||||
png_structp png_ptr = png_create_read_struct
|
||||
|
@ -76,12 +74,8 @@ get_PNG_data(capabilities_t *scanner, int *w, int *h, int *components)
|
|||
if (!png_ptr)
|
||||
{
|
||||
DBG( 1, "Escl Png : PNG error create a png read struct\n");
|
||||
if (scanner->tmp)
|
||||
if (scanner->tmp) {
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
}
|
||||
return (SANE_STATUS_INVAL);
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto close_file;
|
||||
}
|
||||
// create a png info struct
|
||||
png_infop info_ptr = png_create_info_struct (png_ptr);
|
||||
|
@ -89,26 +83,19 @@ get_PNG_data(capabilities_t *scanner, int *w, int *h, int *components)
|
|||
{
|
||||
DBG( 1, "Escl Png : PNG error create a png info struct\n");
|
||||
png_destroy_read_struct (&png_ptr, NULL, NULL);
|
||||
if (scanner->tmp) {
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
}
|
||||
return (SANE_STATUS_INVAL);
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto close_file;
|
||||
}
|
||||
// initialize the setjmp for returning properly after a libpng
|
||||
// error occured
|
||||
if (setjmp (png_jmpbuf (png_ptr)))
|
||||
{
|
||||
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
|
||||
if (texels)
|
||||
free (texels);
|
||||
fprintf(stderr,"PNG read error.\n");
|
||||
if (scanner->tmp) {
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
}
|
||||
if (surface)
|
||||
free (surface);
|
||||
DBG( 1, "Escl Png : PNG read error.\n");
|
||||
return (SANE_STATUS_INVAL);
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto close_file;
|
||||
}
|
||||
// setup libpng for using standard C fread() function
|
||||
// with our FILE pointer
|
||||
|
@ -128,63 +115,79 @@ get_PNG_data(capabilities_t *scanner, int *w, int *h, int *components)
|
|||
png_set_palette_to_rgb (png_ptr);
|
||||
else if (color_type != PNG_COLOR_TYPE_RGB && color_type != PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
{
|
||||
fprintf(stderr,"PNG format not supported.\n");
|
||||
if (scanner->tmp) {
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
}
|
||||
return (SANE_STATUS_INVAL);
|
||||
DBG(1, "PNG format not supported.\n");
|
||||
status = SANE_STATUS_NO_MEM;
|
||||
goto close_file;
|
||||
}
|
||||
if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
bps = 4;
|
||||
else
|
||||
bps = 3;
|
||||
if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha (png_ptr);
|
||||
if (bit_depth == 16)
|
||||
png_set_strip_16 (png_ptr);
|
||||
else if (bit_depth < 8)
|
||||
png_set_packing (png_ptr);
|
||||
// update info structure to apply transformations
|
||||
png_read_update_info (png_ptr, info_ptr);
|
||||
// retrieve updated information
|
||||
png_get_IHDR (png_ptr, info_ptr,
|
||||
(png_uint_32*)(&width),
|
||||
(png_uint_32*)(&height),
|
||||
&bit_depth, &color_type,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
*w = (int)width;
|
||||
*h = (int)height;
|
||||
*components = bps;
|
||||
// we can now allocate memory for storing pixel data
|
||||
texels = (unsigned char *)malloc (sizeof (unsigned char) * width
|
||||
* height * bps);
|
||||
png_bytep *row_pointers;
|
||||
// setup a pointer array. Each one points at the begening of a row.
|
||||
row_pointers = (png_bytep *)malloc (sizeof (png_bytep) * height);
|
||||
for (i = 0; i < height; ++i)
|
||||
{
|
||||
row_pointers[i] = (png_bytep)(texels +
|
||||
((height - (i + 1)) * width * bps));
|
||||
}
|
||||
// read pixel data using row pointers
|
||||
png_read_image (png_ptr, row_pointers);
|
||||
// we don't need row pointers anymore
|
||||
scanner->img_data = texels;
|
||||
scanner->img_size = (int)(width * height * bps);
|
||||
scanner->img_read = 0;
|
||||
free (row_pointers);
|
||||
fclose(scanner->tmp);
|
||||
if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
components = 4;
|
||||
else
|
||||
components = 3;
|
||||
|
||||
if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha (png_ptr);
|
||||
if (bit_depth == 16)
|
||||
png_set_strip_16 (png_ptr);
|
||||
else if (bit_depth < 8)
|
||||
png_set_packing (png_ptr);
|
||||
// update info structure to apply transformations
|
||||
png_read_update_info (png_ptr, info_ptr);
|
||||
// retrieve updated information
|
||||
png_get_IHDR (png_ptr, info_ptr,
|
||||
(png_uint_32*)(&w),
|
||||
(png_uint_32*)(&h),
|
||||
&bit_depth, &color_type,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
*bps = components;
|
||||
// we can now allocate memory for storing pixel data
|
||||
surface = (unsigned char *)malloc (sizeof (unsigned char) * w
|
||||
* h * components);
|
||||
if (!surface) {
|
||||
DBG( 1, "Escl Png : texels Memory allocation problem\n");
|
||||
status = SANE_STATUS_NO_MEM;
|
||||
goto close_file;
|
||||
}
|
||||
png_bytep *row_pointers;
|
||||
// setup a pointer array. Each one points at the begening of a row.
|
||||
row_pointers = (png_bytep *)malloc (sizeof (png_bytep) * h);
|
||||
if (!row_pointers) {
|
||||
DBG( 1, "Escl Png : row_pointers Memory allocation problem\n");
|
||||
free(surface);
|
||||
status = SANE_STATUS_NO_MEM;
|
||||
goto close_file;
|
||||
}
|
||||
for (i = 0; i < h; ++i)
|
||||
{
|
||||
row_pointers[i] = (png_bytep)(surface +
|
||||
((h - (i + 1)) * w * components));
|
||||
}
|
||||
// read pixel data using row pointers
|
||||
png_read_image (png_ptr, row_pointers);
|
||||
|
||||
// If necessary, trim the image.
|
||||
surface = escl_crop_surface(scanner, surface, w, h, components, width, height);
|
||||
if (!surface) {
|
||||
DBG( 1, "Escl Png : Surface Memory allocation problem\n");
|
||||
status = SANE_STATUS_NO_MEM;
|
||||
goto close_file;
|
||||
}
|
||||
|
||||
free (row_pointers);
|
||||
|
||||
close_file:
|
||||
if (scanner->tmp)
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
return (SANE_STATUS_GOOD);
|
||||
return (status);
|
||||
}
|
||||
#else
|
||||
|
||||
SANE_Status
|
||||
get_PNG_data(capabilities_t __sane_unused__ *scanner,
|
||||
int __sane_unused__ *w,
|
||||
int __sane_unused__ *h,
|
||||
int __sane_unused__ *width,
|
||||
int __sane_unused__ *height,
|
||||
int __sane_unused__ *bps)
|
||||
{
|
||||
return (SANE_STATUS_INVAL);
|
||||
|
|
|
@ -31,13 +31,22 @@
|
|||
|
||||
#include <curl/curl.h>
|
||||
|
||||
static size_t
|
||||
write_callback(void __sane_unused__*str,
|
||||
size_t __sane_unused__ size,
|
||||
size_t nmemb,
|
||||
void __sane_unused__ *userp)
|
||||
{
|
||||
return nmemb;
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn void escl_scanner(SANE_String_Const name, char *result)
|
||||
* \fn void escl_scanner(const ESCL_Device *device, char *result)
|
||||
* \brief Function that resets the scanner after each scan, using curl.
|
||||
* This function is called in the 'sane_cancel' function.
|
||||
*/
|
||||
void
|
||||
escl_scanner(SANE_String_Const name, char *result)
|
||||
escl_scanner(const ESCL_Device *device, char *result)
|
||||
{
|
||||
CURL *curl_handle = NULL;
|
||||
const char *scan_jobs = "/eSCL/ScanJobs";
|
||||
|
@ -46,30 +55,25 @@ escl_scanner(SANE_String_Const name, char *result)
|
|||
int i = 0;
|
||||
long answer = 0;
|
||||
|
||||
if (name == NULL || result == NULL)
|
||||
if (device == NULL || result == NULL)
|
||||
return;
|
||||
CURL_CALL:
|
||||
curl_handle = curl_easy_init();
|
||||
if (curl_handle != NULL) {
|
||||
strcpy(scan_cmd, name);
|
||||
strcat(scan_cmd, scan_jobs);
|
||||
strcat(scan_cmd, result);
|
||||
strcat(scan_cmd, scanner_start);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_URL, scan_cmd);
|
||||
DBG( 1, "Reset Job : %s.\n", scan_cmd);
|
||||
if (strncmp(name, "https", 5) == 0) {
|
||||
DBG( 1, "Ignoring safety certificates, use https\n");
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
}
|
||||
snprintf(scan_cmd, sizeof(scan_cmd), "%s%s%s",
|
||||
scan_jobs, result, scanner_start);
|
||||
escl_curl_url(curl_handle, device, scan_cmd);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_callback);
|
||||
if (curl_easy_perform(curl_handle) == CURLE_OK) {
|
||||
curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &answer);
|
||||
if (i < 3 && answer == 503) {
|
||||
curl_easy_cleanup(curl_handle);
|
||||
i++;
|
||||
goto CURL_CALL;
|
||||
}
|
||||
i++;
|
||||
if (i >= 15) return;
|
||||
}
|
||||
curl_easy_cleanup(curl_handle);
|
||||
if (SANE_STATUS_GOOD != escl_status(device,
|
||||
PLATEN,
|
||||
NULL,
|
||||
NULL))
|
||||
goto CURL_CALL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,13 +43,14 @@
|
|||
static size_t
|
||||
write_callback(void *str, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
size_t to_write = fwrite(str, size, nmemb, (FILE *)userp);
|
||||
|
||||
capabilities_t *scanner = (capabilities_t *)userp;
|
||||
size_t to_write = fwrite(str, size, nmemb, scanner->tmp);
|
||||
scanner->real_read += to_write;
|
||||
return (to_write);
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn SANE_Status escl_scan(capabilities_t *scanner, SANE_String_Const name, char *result)
|
||||
* \fn SANE_Status escl_scan(capabilities_t *scanner, const ESCL_Device *device, char *result)
|
||||
* \brief Function that, after recovering the 'new job', scans the image writed in the
|
||||
* temporary file, using curl.
|
||||
* This function is called in the 'sane_start' function and it's the equivalent of
|
||||
|
@ -58,7 +59,7 @@ write_callback(void *str, size_t size, size_t nmemb, void *userp)
|
|||
* \return status (if everything is OK, status = SANE_STATUS_GOOD, otherwise, SANE_STATUS_NO_MEM/SANE_STATUS_INVAL)
|
||||
*/
|
||||
SANE_Status
|
||||
escl_scan(capabilities_t __sane_unused__ *scanner, SANE_String_Const name, char *result)
|
||||
escl_scan(capabilities_t *scanner, const ESCL_Device *device, char *result)
|
||||
{
|
||||
CURL *curl_handle = NULL;
|
||||
const char *scan_jobs = "/eSCL/ScanJobs";
|
||||
|
@ -66,34 +67,41 @@ escl_scan(capabilities_t __sane_unused__ *scanner, SANE_String_Const name, char
|
|||
char scan_cmd[PATH_MAX] = { 0 };
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
|
||||
if (name == NULL)
|
||||
if (device == NULL)
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
scanner->real_read = 0;
|
||||
curl_handle = curl_easy_init();
|
||||
if (curl_handle != NULL) {
|
||||
strcpy(scan_cmd, name);
|
||||
strcat(scan_cmd, scan_jobs);
|
||||
strcat(scan_cmd, result);
|
||||
strcat(scan_cmd, scanner_start);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_URL, scan_cmd);
|
||||
DBG( 1, "Scan : %s.\n", scan_cmd);
|
||||
if (strncmp(name, "https", 5) == 0) {
|
||||
DBG( 1, "Ignoring safety certificates, use https\n");
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
}
|
||||
snprintf(scan_cmd, sizeof(scan_cmd), "%s%s%s",
|
||||
scan_jobs, result, scanner_start);
|
||||
escl_curl_url(curl_handle, device, scan_cmd);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_callback);
|
||||
if (scanner->tmp)
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = tmpfile();
|
||||
if (scanner->tmp != NULL) {
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, scanner->tmp);
|
||||
if (curl_easy_perform(curl_handle) != CURLE_OK) {
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, scanner);
|
||||
CURLcode res = curl_easy_perform(curl_handle);
|
||||
if (res != CURLE_OK) {
|
||||
DBG( 1, "Unable to scan: %s\n", curl_easy_strerror(res));
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
else
|
||||
curl_easy_cleanup(curl_handle);
|
||||
fseek(scanner->tmp, 0, SEEK_SET);
|
||||
}
|
||||
else
|
||||
status = SANE_STATUS_NO_MEM;
|
||||
cleanup:
|
||||
curl_easy_cleanup(curl_handle);
|
||||
}
|
||||
DBG(10, "eSCL scan : [%s]\treal read (%ld)\n", sane_strstatus(status), scanner->real_read);
|
||||
if (scanner->real_read == 0)
|
||||
{
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
return SANE_STATUS_NO_DOCS;
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
|
|
@ -83,34 +83,105 @@ find_nodes_s(xmlNode *node)
|
|||
return (1);
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn static void print_xml_s(xmlNode *node, SANE_Status *status)
|
||||
* \brief Function that browses the xml file, node by node.
|
||||
* If the node 'State' is found, we are expecting to found in this node the 'Idle'
|
||||
* content (if the scanner is ready to use) and then 'status' = SANE_STATUS_GOOD.
|
||||
* Otherwise, this means that the scanner isn't ready to use.
|
||||
*/
|
||||
static void
|
||||
print_xml_s(xmlNode *node, SANE_Status *status)
|
||||
print_xml_job_status(xmlNode *node,
|
||||
SANE_Status *job,
|
||||
int *image)
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
while (node) {
|
||||
if (node->type == XML_ELEMENT_NODE) {
|
||||
if (find_nodes_s(node)) {
|
||||
if (strcmp((const char *)node->name, "State") == 0)
|
||||
x = 1;
|
||||
if (strcmp((const char *)node->name, "JobState") == 0) {
|
||||
const char *state = (const char *)xmlNodeGetContent(node);
|
||||
if (!strcmp(state, "Processing")) {
|
||||
*job = SANE_STATUS_DEVICE_BUSY;
|
||||
DBG(10, "jobId Processing SANE_STATUS_DEVICE_BUSY\n");
|
||||
}
|
||||
else if (!strcmp(state, "Completed")) {
|
||||
*job = SANE_STATUS_GOOD;
|
||||
DBG(10, "jobId Completed SANE_STATUS_GOOD\n");
|
||||
}
|
||||
else if (strcmp((const char *)node->name, "ImagesToTransfer") == 0) {
|
||||
const char *state = (const char *)xmlNodeGetContent(node);
|
||||
*image = atoi(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (x == 1 && strcmp((const char *)xmlNodeGetContent(node), "Idle") == 0)
|
||||
*status = SANE_STATUS_GOOD;
|
||||
}
|
||||
print_xml_s(node->children, status);
|
||||
print_xml_job_status(node->children, job, image);
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_xml_platen_and_adf_status(xmlNode *node,
|
||||
SANE_Status *platen,
|
||||
SANE_Status *adf,
|
||||
const char* jobId,
|
||||
SANE_Status *job,
|
||||
int *image)
|
||||
{
|
||||
while (node) {
|
||||
if (node->type == XML_ELEMENT_NODE) {
|
||||
if (find_nodes_s(node)) {
|
||||
if (strcmp((const char *)node->name, "State") == 0) {
|
||||
printf ("State\t");
|
||||
const char *state = (const char *)xmlNodeGetContent(node);
|
||||
if (!strcmp(state, "Idle")) {
|
||||
DBG(10, "Idle SANE_STATUS_GOOD\n");
|
||||
*platen = SANE_STATUS_GOOD;
|
||||
} else if (!strcmp(state, "Processing")) {
|
||||
DBG(10, "Processing SANE_STATUS_DEVICE_BUSY\n");
|
||||
*platen = SANE_STATUS_DEVICE_BUSY;
|
||||
} else {
|
||||
DBG(10, "%s SANE_STATUS_UNSUPPORTED\n", state);
|
||||
*platen = SANE_STATUS_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
// Thank's Alexander Pevzner (pzz@apevzner.com)
|
||||
else if (adf && strcmp((const char *)node->name, "AdfState") == 0) {
|
||||
const char *state = (const char *)xmlNodeGetContent(node);
|
||||
if (!strcmp(state, "ScannerAdfLoaded")){
|
||||
DBG(10, "ScannerAdfLoaded SANE_STATUS_GOOD\n");
|
||||
*adf = SANE_STATUS_GOOD;
|
||||
} else if (!strcmp(state, "ScannerAdfJam")) {
|
||||
DBG(10, "ScannerAdfJam SANE_STATUS_JAMMED\n");
|
||||
*adf = SANE_STATUS_JAMMED;
|
||||
} else if (!strcmp(state, "ScannerAdfDoorOpen")) {
|
||||
DBG(10, "ScannerAdfDoorOpen SANE_STATUS_COVER_OPEN\n");
|
||||
*adf = SANE_STATUS_COVER_OPEN;
|
||||
} else if (!strcmp(state, "ScannerAdfProcessing")) {
|
||||
/* Kyocera version */
|
||||
DBG(10, "ScannerAdfProcessing SANE_STATUS_NO_DOC\n");
|
||||
*adf = SANE_STATUS_NO_DOCS;
|
||||
} else if (!strcmp(state, "ScannerAdfEmpty")) {
|
||||
DBG(10, "ScannerAdfEmpty SANE_STATUS_NO_DOCS\n");
|
||||
/* Cannon TR4500, EPSON XP-7100 */
|
||||
*adf = SANE_STATUS_NO_DOCS;
|
||||
} else {
|
||||
DBG(10, "%s SANE_STATUS_NO_DOCS\n", state);
|
||||
*adf = SANE_STATUS_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
else if (jobId && job && strcmp((const char *)node->name, "JobUri") == 0) {
|
||||
if (strstr((const char *)xmlNodeGetContent(node), jobId)) {
|
||||
print_xml_job_status(node, job, image);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
print_xml_platen_and_adf_status(node->children,
|
||||
platen,
|
||||
adf,
|
||||
jobId,
|
||||
job,
|
||||
image);
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn SANE_Status escl_status(SANE_String_Const name)
|
||||
* \fn SANE_Status escl_status(const ESCL_Device *device)
|
||||
* \brief Function that finally recovers the scanner status ('Idle', or not), using curl.
|
||||
* This function is called in the 'sane_open' function and it's the equivalent of
|
||||
* the following curl command : "curl http(s)://'ip':'port'/eSCL/ScannerStatus".
|
||||
|
@ -118,40 +189,45 @@ print_xml_s(xmlNode *node, SANE_Status *status)
|
|||
* \return status (if everything is OK, status = SANE_STATUS_GOOD, otherwise, SANE_STATUS_NO_MEM/SANE_STATUS_INVAL)
|
||||
*/
|
||||
SANE_Status
|
||||
escl_status(SANE_String_Const name)
|
||||
escl_status(const ESCL_Device *device,
|
||||
int source,
|
||||
const char* jobId,
|
||||
SANE_Status *job)
|
||||
{
|
||||
SANE_Status status;
|
||||
SANE_Status status = SANE_STATUS_DEVICE_BUSY;
|
||||
SANE_Status platen= SANE_STATUS_DEVICE_BUSY;
|
||||
SANE_Status adf= SANE_STATUS_DEVICE_BUSY;
|
||||
CURL *curl_handle = NULL;
|
||||
struct idle *var = NULL;
|
||||
xmlDoc *data = NULL;
|
||||
xmlNode *node = NULL;
|
||||
const char *scanner_status = "/eSCL/ScannerStatus";
|
||||
char tmp[PATH_MAX] = { 0 };
|
||||
int image = -1;
|
||||
int pass = 0;
|
||||
reload:
|
||||
|
||||
if (name == NULL)
|
||||
if (device == NULL)
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
status = SANE_STATUS_DEVICE_BUSY;
|
||||
platen= SANE_STATUS_DEVICE_BUSY;
|
||||
adf= SANE_STATUS_DEVICE_BUSY;
|
||||
var = (struct idle*)calloc(1, sizeof(struct idle));
|
||||
if (var == NULL)
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
var->memory = malloc(1);
|
||||
var->size = 0;
|
||||
curl_handle = curl_easy_init();
|
||||
strcpy(tmp, name);
|
||||
strcat(tmp, scanner_status);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_URL, tmp);
|
||||
DBG( 1, "Get Status : %s.\n", tmp);
|
||||
if (strncmp(name, "https", 5) == 0) {
|
||||
DBG( 1, "Ignoring safety certificates, use https\n");
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
}
|
||||
|
||||
escl_curl_url(curl_handle, device, scanner_status);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, memory_callback_s);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)var);
|
||||
if (curl_easy_perform(curl_handle) != CURLE_OK) {
|
||||
DBG( 1, "The scanner didn't respond.\n");
|
||||
CURLcode res = curl_easy_perform(curl_handle);
|
||||
if (res != CURLE_OK) {
|
||||
DBG( 1, "The scanner didn't respond: %s\n", curl_easy_strerror(res));
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto clean_data;
|
||||
}
|
||||
DBG( 10, "eSCL : Status : %s.\n", var->memory);
|
||||
data = xmlReadMemory(var->memory, var->size, "file.xml", NULL, 0);
|
||||
if (data == NULL) {
|
||||
status = SANE_STATUS_NO_MEM;
|
||||
|
@ -162,8 +238,18 @@ escl_status(SANE_String_Const name)
|
|||
status = SANE_STATUS_NO_MEM;
|
||||
goto clean;
|
||||
}
|
||||
status = SANE_STATUS_DEVICE_BUSY;
|
||||
print_xml_s(node, &status);
|
||||
/* Decode Job status */
|
||||
// Thank's Alexander Pevzner (pzz@apevzner.com)
|
||||
print_xml_platen_and_adf_status(node, &platen, &adf, jobId, job, &image);
|
||||
if (platen != SANE_STATUS_GOOD &&
|
||||
platen != SANE_STATUS_UNSUPPORTED) {
|
||||
status = platen;
|
||||
} else if (source == PLATEN) {
|
||||
status = platen;
|
||||
} else {
|
||||
status = adf;
|
||||
}
|
||||
DBG (10, "STATUS : %s\n", sane_strstatus(status));
|
||||
clean:
|
||||
xmlFreeDoc(data);
|
||||
clean_data:
|
||||
|
@ -172,5 +258,14 @@ clean_data:
|
|||
curl_easy_cleanup(curl_handle);
|
||||
free(var->memory);
|
||||
free(var);
|
||||
if (pass == 0 &&
|
||||
source != PLATEN &&
|
||||
image == 0 &&
|
||||
(status == SANE_STATUS_GOOD ||
|
||||
status == SANE_STATUS_UNSUPPORTED ||
|
||||
status == SANE_STATUS_DEVICE_BUSY)) {
|
||||
pass = 1;
|
||||
goto reload;
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
|
|
@ -50,60 +50,59 @@
|
|||
* \return SANE_STATUS_GOOD (if everything is OK, otherwise, SANE_STATUS_NO_MEM/SANE_STATUS_INVAL)
|
||||
*/
|
||||
SANE_Status
|
||||
get_TIFF_data(capabilities_t *scanner, int *w, int *h, int *components)
|
||||
get_TIFF_data(capabilities_t *scanner, int *width, int *height, int *bps)
|
||||
{
|
||||
TIFF* tif = NULL;
|
||||
uint32 width = 0; /* largeur */
|
||||
uint32 height = 0; /* hauteur */
|
||||
unsigned char *raster = NULL; /* données de l'image */
|
||||
int bps = 4;
|
||||
uint32 w = 0;
|
||||
uint32 h = 0;
|
||||
unsigned char *surface = NULL; /* image data*/
|
||||
int components = 4;
|
||||
uint32 npixels = 0;
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
|
||||
lseek(fileno(scanner->tmp), 0, SEEK_SET);
|
||||
tif = TIFFFdOpen(fileno(scanner->tmp), "temp", "r");
|
||||
if (!tif) {
|
||||
DBG( 1, "Escl Tiff : Can not open, or not a TIFF file.\n");
|
||||
if (scanner->tmp) {
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
}
|
||||
return (SANE_STATUS_INVAL);
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto close_file;
|
||||
}
|
||||
|
||||
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
|
||||
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
|
||||
npixels = width * height;
|
||||
raster = (unsigned char*) malloc(npixels * sizeof (uint32));
|
||||
if (raster != NULL)
|
||||
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
|
||||
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
|
||||
npixels = w * h;
|
||||
surface = (unsigned char*) malloc(npixels * sizeof (uint32));
|
||||
if (surface != NULL)
|
||||
{
|
||||
DBG( 1, "Escl Tiff : Memory allocation problem.\n");
|
||||
if (scanner->tmp) {
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
}
|
||||
return (SANE_STATUS_INVAL);
|
||||
DBG( 1, "Escl Tiff : raster Memory allocation problem.\n");
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto close_tiff;
|
||||
}
|
||||
|
||||
if (!TIFFReadRGBAImage(tif, width, height, (uint32 *)raster, 0))
|
||||
if (!TIFFReadRGBAImage(tif, w, h, (uint32 *)surface, 0))
|
||||
{
|
||||
DBG( 1, "Escl Tiff : Problem reading image data.\n");
|
||||
if (scanner->tmp) {
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
}
|
||||
return (SANE_STATUS_INVAL);
|
||||
status = SANE_STATUS_INVAL;
|
||||
free(surface);
|
||||
goto close_tiff;
|
||||
}
|
||||
*w = (int)width;
|
||||
*h = (int)height;
|
||||
*components = bps;
|
||||
// we don't need row pointers anymore
|
||||
scanner->img_data = raster;
|
||||
scanner->img_size = (int)(width * height * bps);
|
||||
scanner->img_read = 0;
|
||||
|
||||
*bps = components;
|
||||
|
||||
// If necessary, trim the image.
|
||||
surface = escl_crop_surface(scanner, surface, w, h, components, width, height);
|
||||
if (!surface) {
|
||||
DBG( 1, "Escl Tiff : Surface Memory allocation problem\n");
|
||||
status = SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
close_tiff:
|
||||
TIFFClose(tif);
|
||||
fclose(scanner->tmp);
|
||||
close_file:
|
||||
if (scanner->tmp)
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
return (SANE_STATUS_GOOD);
|
||||
return (status);
|
||||
}
|
||||
#else
|
||||
|
||||
|
|
|
@ -383,6 +383,9 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
|
|||
|
||||
#define get_IN_op_halt(in) getbitfield(in+0x7a, 1, 7)
|
||||
|
||||
#define get_IN_return_path(in) getbitfield(in+0x7c, 1, 7)
|
||||
#define get_IN_energy_star3(in) getbitfield(in+0x7c, 1, 6)
|
||||
|
||||
/* ==================================================================== */
|
||||
/* page codes used by mode_sense and mode_select */
|
||||
#define MS_pc_unk 0x2c /* Used by iX500 */
|
||||
|
@ -763,6 +766,7 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
|
|||
#define get_GHS_fb_open(in) getbitfield(in+0x03, 1, 3)
|
||||
#define get_GHS_paper_end(in) getbitfield(in+0x03, 1, 2)
|
||||
#define get_GHS_fb_on(in) getbitfield(in+0x03, 1, 1)
|
||||
#define get_GHS_exit(in) getbitfield(in+0x03, 1, 0)
|
||||
|
||||
#define get_GHS_sleep(in) getbitfield(in+0x04, 1, 7)
|
||||
#define get_GHS_clean(in) getbitfield(in+0x04, 1, 6)
|
||||
|
@ -823,7 +827,8 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
|
|||
#define SCANNER_CONTROL_len 10
|
||||
|
||||
#define set_SC_ric(icb, val) setbitfield(icb + 1, 1, 4, val)
|
||||
#define set_SC_function(icb, val) setbitfield(icb + 1, 0xf, 0, val)
|
||||
#define set_SC_function_1(icb, val) setbitfield(icb + 1, 0xf, 0, val)
|
||||
#define set_SC_function_2(icb, val) icb[2] = (val >> 4)
|
||||
#define SC_function_adf 0x00
|
||||
#define SC_function_fb 0x01
|
||||
#define SC_function_fb_hs 0x02
|
||||
|
@ -836,6 +841,9 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
|
|||
#define SC_function_scan_complete 0x09
|
||||
#define SC_function_eject_complete 0x0a
|
||||
#define SC_function_manual_feed 0x0c
|
||||
#define SC_function_mfeed 0x0f
|
||||
#define SC_function_continuous 0x1f
|
||||
#define SC_function_rpath 0x2f
|
||||
|
||||
/* used with SC_function_panel */
|
||||
#define set_SC_led_eb(icb, val) setbitfield(icb + 5, 1, 7, val)
|
||||
|
|
|
@ -603,8 +603,12 @@
|
|||
v134 2019-02-23, MAN
|
||||
- rewrite init_vpd for scanners which fail to report
|
||||
overscan correctly
|
||||
v135 2019-11-10, MAN
|
||||
v135 2019-11-10, MAN (SANE 1.0.29)
|
||||
- set has_MS_lamp=0 for fi-72x0, bug #134
|
||||
v136 2020-02-07, MAN
|
||||
- add support for fi-800R
|
||||
- add support for card scanning slot (Return Path)
|
||||
- fix bug with reading hardware sensors on first invocation
|
||||
|
||||
SANE FLOW DIAGRAM
|
||||
|
||||
|
@ -654,7 +658,7 @@
|
|||
#include "fujitsu.h"
|
||||
|
||||
#define DEBUG 1
|
||||
#define BUILD 134
|
||||
#define BUILD 136
|
||||
|
||||
/* values for SANE_DEBUG_FUJITSU env var:
|
||||
- errors 5
|
||||
|
@ -678,6 +682,9 @@
|
|||
#define STRING_ADFFRONT SANE_I18N("ADF Front")
|
||||
#define STRING_ADFBACK SANE_I18N("ADF Back")
|
||||
#define STRING_ADFDUPLEX SANE_I18N("ADF Duplex")
|
||||
#define STRING_CARDFRONT SANE_I18N("Card Front")
|
||||
#define STRING_CARDBACK SANE_I18N("Card Back")
|
||||
#define STRING_CARDDUPLEX SANE_I18N("Card Duplex")
|
||||
|
||||
#define STRING_LINEART SANE_VALUE_SCAN_MODE_LINEART
|
||||
#define STRING_HALFTONE SANE_VALUE_SCAN_MODE_HALFTONE
|
||||
|
@ -1821,6 +1828,12 @@ init_vpd (struct fujitsu *s)
|
|||
DBG (15, " object position halt: %d\n", s->has_op_halt);
|
||||
}
|
||||
|
||||
if (payload_off >= 0x7c) {
|
||||
s->has_return_path = get_IN_return_path(in);
|
||||
DBG (15, " return path (card) scanning: %d\n", s->has_return_path);
|
||||
DBG (15, " energy star 3: %d\n", get_IN_energy_star3(in));
|
||||
}
|
||||
|
||||
DBG (10, "init_vpd: finish\n");
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
|
@ -2498,6 +2511,8 @@ init_user (struct fujitsu *s)
|
|||
s->source = SOURCE_FLATBED;
|
||||
else if(s->has_adf)
|
||||
s->source = SOURCE_ADF_FRONT;
|
||||
else if(s->has_return_path)
|
||||
s->source = SOURCE_CARD_FRONT;
|
||||
|
||||
/* scan mode */
|
||||
if(s->can_mode[MODE_LINEART])
|
||||
|
@ -2875,6 +2890,16 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
|
|||
s->source_list[i++]=STRING_ADFDUPLEX;
|
||||
}
|
||||
}
|
||||
if(s->has_return_path){
|
||||
s->source_list[i++]=STRING_CARDFRONT;
|
||||
|
||||
if(s->has_back){
|
||||
s->source_list[i++]=STRING_CARDBACK;
|
||||
}
|
||||
if(s->has_duplex){
|
||||
s->source_list[i++]=STRING_CARDDUPLEX;
|
||||
}
|
||||
}
|
||||
s->source_list[i]=NULL;
|
||||
|
||||
opt->name = SANE_NAME_SCAN_SOURCE;
|
||||
|
@ -3049,7 +3074,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
|
|||
opt->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
opt->constraint.range = &s->paper_x_range;
|
||||
|
||||
if(s->has_adf){
|
||||
if(s->has_adf || s->has_return_path){
|
||||
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||||
if(s->source == SOURCE_FLATBED){
|
||||
opt->cap |= SANE_CAP_INACTIVE;
|
||||
|
@ -3076,7 +3101,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
|
|||
opt->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
opt->constraint.range = &s->paper_y_range;
|
||||
|
||||
if(s->has_adf){
|
||||
if(s->has_adf || s->has_return_path){
|
||||
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||||
if(s->source == SOURCE_FLATBED){
|
||||
opt->cap |= SANE_CAP_INACTIVE;
|
||||
|
@ -4474,6 +4499,18 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
|
|||
opt->cap = SANE_CAP_INACTIVE;
|
||||
}
|
||||
|
||||
if(option==OPT_CARD_LOADED){
|
||||
opt->name = "card-loaded";
|
||||
opt->title = SANE_I18N ("Card loaded");
|
||||
opt->desc = SANE_I18N ("Card slot contains paper");
|
||||
opt->type = SANE_TYPE_BOOL;
|
||||
opt->unit = SANE_UNIT_NONE;
|
||||
if (s->has_cmd_hw_status && s->has_return_path)
|
||||
opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
|
||||
else
|
||||
opt->cap = SANE_CAP_INACTIVE;
|
||||
}
|
||||
|
||||
if(option==OPT_SLEEP){
|
||||
opt->name = "power-save";
|
||||
opt->title = SANE_I18N ("Power saving");
|
||||
|
@ -4697,6 +4734,15 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
|
|||
else if(s->source == SOURCE_ADF_DUPLEX){
|
||||
strcpy (val, STRING_ADFDUPLEX);
|
||||
}
|
||||
else if(s->source == SOURCE_CARD_FRONT){
|
||||
strcpy (val, STRING_CARDFRONT);
|
||||
}
|
||||
else if(s->source == SOURCE_CARD_BACK){
|
||||
strcpy (val, STRING_CARDBACK);
|
||||
}
|
||||
else if(s->source == SOURCE_CARD_DUPLEX){
|
||||
strcpy (val, STRING_CARDDUPLEX);
|
||||
}
|
||||
return SANE_STATUS_GOOD;
|
||||
|
||||
case OPT_MODE:
|
||||
|
@ -5215,6 +5261,11 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
|
|||
*val_p = s->hw_adf_open;
|
||||
return ret;
|
||||
|
||||
case OPT_CARD_LOADED:
|
||||
ret = get_hardware_status(s,option);
|
||||
*val_p = s->hw_card_loaded;
|
||||
return ret;
|
||||
|
||||
case OPT_SLEEP:
|
||||
ret = get_hardware_status(s,option);
|
||||
*val_p = s->hw_sleep;
|
||||
|
@ -5323,6 +5374,15 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
|
|||
else if (!strcmp (val, STRING_ADFDUPLEX)) {
|
||||
tmp = SOURCE_ADF_DUPLEX;
|
||||
}
|
||||
else if (!strcmp (val, STRING_CARDFRONT)) {
|
||||
tmp = SOURCE_CARD_FRONT;
|
||||
}
|
||||
else if (!strcmp (val, STRING_CARDBACK)) {
|
||||
tmp = SOURCE_CARD_BACK;
|
||||
}
|
||||
else if (!strcmp (val, STRING_CARDDUPLEX)) {
|
||||
tmp = SOURCE_CARD_DUPLEX;
|
||||
}
|
||||
else{
|
||||
tmp = SOURCE_FLATBED;
|
||||
}
|
||||
|
@ -5912,12 +5972,12 @@ get_hardware_status (struct fujitsu *s, SANE_Int option)
|
|||
|
||||
/* only run this if frontend has already read the last time we got it */
|
||||
/* or if we don't care for such bookkeeping (private use) */
|
||||
if (!option || s->hw_read[option-OPT_TOP]) {
|
||||
if (!option || !s->hw_data_avail[option-OPT_TOP]) {
|
||||
|
||||
DBG (15, "get_hardware_status: running\n");
|
||||
|
||||
/* mark all values as unread */
|
||||
memset(s->hw_read,0,sizeof(s->hw_read));
|
||||
/* mark all values as available */
|
||||
memset(s->hw_data_avail,1,sizeof(s->hw_data_avail));
|
||||
|
||||
if (s->has_cmd_hw_status){
|
||||
unsigned char cmd[GET_HW_STATUS_len];
|
||||
|
@ -5950,6 +6010,7 @@ get_hardware_status (struct fujitsu *s, SANE_Int option)
|
|||
s->hw_hopper = get_GHS_hopper(in);
|
||||
s->hw_omr = get_GHS_omr(in);
|
||||
s->hw_adf_open = get_GHS_adf_open(in);
|
||||
s->hw_card_loaded = get_GHS_exit(in);
|
||||
|
||||
s->hw_sleep = get_GHS_sleep(in);
|
||||
s->hw_send_sw = get_GHS_send_sw(in);
|
||||
|
@ -6015,7 +6076,7 @@ get_hardware_status (struct fujitsu *s, SANE_Int option)
|
|||
}
|
||||
|
||||
if(option)
|
||||
s->hw_read[option-OPT_TOP] = 1;
|
||||
s->hw_data_avail[option-OPT_TOP] = 0;
|
||||
|
||||
DBG (10, "get_hardware_status: finish\n");
|
||||
|
||||
|
@ -6905,8 +6966,8 @@ sane_start (SANE_Handle handle)
|
|||
}
|
||||
|
||||
/* low mem mode messes up the side marker, reset it */
|
||||
if(s->source == SOURCE_ADF_DUPLEX && s->low_mem
|
||||
&& s->eof_tx[SIDE_FRONT] && s->eof_tx[SIDE_BACK]
|
||||
if((s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX)
|
||||
&& s->low_mem && s->eof_tx[SIDE_FRONT] && s->eof_tx[SIDE_BACK]
|
||||
){
|
||||
s->side = SIDE_BACK;
|
||||
}
|
||||
|
@ -6915,7 +6976,7 @@ sane_start (SANE_Handle handle)
|
|||
if(!s->started){
|
||||
|
||||
/* load side marker */
|
||||
if(s->source == SOURCE_ADF_BACK){
|
||||
if(s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK){
|
||||
s->side = SIDE_BACK;
|
||||
}
|
||||
else{
|
||||
|
@ -6936,6 +6997,12 @@ sane_start (SANE_Handle handle)
|
|||
DBG (5, "sane_start: ERROR: cannot control fb, ignoring\n");
|
||||
}
|
||||
}
|
||||
else if(s->source == SOURCE_CARD_FRONT || s->source == SOURCE_CARD_BACK || s->source == SOURCE_CARD_DUPLEX){
|
||||
ret = scanner_control(s, SC_function_rpath);
|
||||
if (ret != SANE_STATUS_GOOD) {
|
||||
DBG (5, "sane_start: ERROR: cannot control rp, ignoring\n");
|
||||
}
|
||||
}
|
||||
else{
|
||||
ret = scanner_control(s, SC_function_adf);
|
||||
if (ret != SANE_STATUS_GOOD) {
|
||||
|
@ -7038,7 +7105,7 @@ sane_start (SANE_Handle handle)
|
|||
}
|
||||
}
|
||||
/* if already running, duplex needs to switch sides */
|
||||
else if(s->source == SOURCE_ADF_DUPLEX){
|
||||
else if(s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX){
|
||||
s->side = !s->side;
|
||||
}
|
||||
|
||||
|
@ -7047,7 +7114,7 @@ sane_start (SANE_Handle handle)
|
|||
/* otherwise buffered back page will be lost */
|
||||
/* ingest paper with adf (no-op for fb) */
|
||||
/* dont call object pos or scan on back side of duplex scan */
|
||||
if(s->side == SIDE_FRONT || s->source == SOURCE_ADF_BACK){
|
||||
if(s->side == SIDE_FRONT || s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK){
|
||||
|
||||
s->bytes_rx[0]=0;
|
||||
s->bytes_rx[1]=0;
|
||||
|
@ -7095,7 +7162,7 @@ sane_start (SANE_Handle handle)
|
|||
}
|
||||
|
||||
/* store the number of front bytes */
|
||||
if ( s->source != SOURCE_ADF_BACK ){
|
||||
if ( s->source != SOURCE_ADF_BACK && s->source != SOURCE_CARD_BACK ){
|
||||
s->bytes_tot[SIDE_FRONT] = s->s_params.bytes_per_line * s->s_params.lines;
|
||||
s->buff_tot[SIDE_FRONT] = s->buffer_size;
|
||||
|
||||
|
@ -7114,13 +7181,14 @@ sane_start (SANE_Handle handle)
|
|||
}
|
||||
|
||||
/* store the number of back bytes */
|
||||
if ( s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_ADF_BACK ){
|
||||
if ( s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_ADF_BACK
|
||||
|| s->source == SOURCE_CARD_DUPLEX || s->source == SOURCE_CARD_BACK ){
|
||||
s->bytes_tot[SIDE_BACK] = s->s_params.bytes_per_line * s->s_params.lines;
|
||||
s->buff_tot[SIDE_BACK] = s->bytes_tot[SIDE_BACK];
|
||||
|
||||
/* the back buffer is normally very large, but some scanners or
|
||||
* option combinations dont need it, so we make a small one */
|
||||
if(s->low_mem || s->source == SOURCE_ADF_BACK
|
||||
if(s->low_mem || s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK
|
||||
|| s->duplex_interlace == DUPLEX_INTERLACE_NONE)
|
||||
s->buff_tot[SIDE_BACK] = s->buffer_size;
|
||||
}
|
||||
|
@ -7308,13 +7376,14 @@ scanner_control (struct fujitsu *s, int function)
|
|||
|
||||
memset(cmd,0,cmdLen);
|
||||
set_SCSI_opcode(cmd, SCANNER_CONTROL_code);
|
||||
set_SC_function (cmd, function);
|
||||
set_SC_function_1 (cmd, function);
|
||||
set_SC_function_2 (cmd, function);
|
||||
|
||||
DBG (15, "scanner_control: function %d\n",function);
|
||||
|
||||
/* don't really need to ask for adf if that's the only option */
|
||||
/* doing so causes the 3091 to complain */
|
||||
if(function == SC_function_adf && !s->has_flatbed){
|
||||
if(function == SC_function_adf && !s->has_flatbed && !s->has_return_path){
|
||||
DBG (10, "scanner_control: adf function not required\n");
|
||||
return ret;
|
||||
}
|
||||
|
@ -7486,7 +7555,7 @@ set_window (struct fujitsu *s)
|
|||
set_WPDB_wdblen(header, SW_desc_len);
|
||||
|
||||
/* init the window block */
|
||||
if (s->source == SOURCE_ADF_BACK) {
|
||||
if (s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK) {
|
||||
set_WD_wid (desc1, WD_wid_back);
|
||||
}
|
||||
else{
|
||||
|
@ -7675,7 +7744,7 @@ set_window (struct fujitsu *s)
|
|||
}
|
||||
|
||||
/* when in duplex mode, copy first desc block into second */
|
||||
if (s->source == SOURCE_ADF_DUPLEX) {
|
||||
if (s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX) {
|
||||
memcpy (desc2, desc1, SW_desc_len);
|
||||
|
||||
set_WD_wid (desc2, WD_wid_back);
|
||||
|
@ -7823,7 +7892,7 @@ get_pixelsize(struct fujitsu *s, int actual)
|
|||
}
|
||||
|
||||
/*
|
||||
* Issues the SCSI OBJECT POSITION command if an ADF is in use.
|
||||
* Issues the SCSI OBJECT POSITION command if an ADF or card scanner is in use.
|
||||
*/
|
||||
static SANE_Status
|
||||
object_position (struct fujitsu *s, int action)
|
||||
|
@ -7880,9 +7949,9 @@ start_scan (struct fujitsu *s)
|
|||
|
||||
DBG (10, "start_scan: start\n");
|
||||
|
||||
if (s->source != SOURCE_ADF_DUPLEX) {
|
||||
if (s->source != SOURCE_ADF_DUPLEX && s->source != SOURCE_CARD_DUPLEX) {
|
||||
outLen--;
|
||||
if(s->source == SOURCE_ADF_BACK) {
|
||||
if(s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK) {
|
||||
out[0] = WD_wid_back;
|
||||
}
|
||||
}
|
||||
|
@ -7983,7 +8052,8 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len
|
|||
|
||||
/* swap sides if user asked for low-mem mode, we are duplexing,
|
||||
* and there is data waiting on the other side */
|
||||
if(s->low_mem && s->source == SOURCE_ADF_DUPLEX
|
||||
if(s->low_mem
|
||||
&& (s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX)
|
||||
&& (s->bytes_rx[!s->side] > s->bytes_tx[!s->side]
|
||||
|| (s->eof_rx[!s->side] && !s->eof_tx[!s->side])
|
||||
)
|
||||
|
@ -8013,7 +8083,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len
|
|||
} /* end 3091 */
|
||||
|
||||
/* alternating jpeg duplex interlacing */
|
||||
else if(s->source == SOURCE_ADF_DUPLEX
|
||||
else if((s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX)
|
||||
&& s->s_params.format == SANE_FRAME_JPEG
|
||||
&& s->jpeg_interlace == JPEG_INTERLACE_ALT
|
||||
){
|
||||
|
@ -8025,7 +8095,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len
|
|||
} /* end alt jpeg */
|
||||
|
||||
/* alternating pnm duplex interlacing */
|
||||
else if(s->source == SOURCE_ADF_DUPLEX
|
||||
else if((s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX)
|
||||
&& s->s_params.format != SANE_FRAME_JPEG
|
||||
&& s->duplex_interlace == DUPLEX_INTERLACE_ALT
|
||||
){
|
||||
|
@ -8080,7 +8150,8 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len
|
|||
|
||||
/* swap sides if user asked for low-mem mode, we are duplexing,
|
||||
* and there is data waiting on the other side */
|
||||
if(s->low_mem && s->source == SOURCE_ADF_DUPLEX
|
||||
if(s->low_mem
|
||||
&& (s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX)
|
||||
&& (s->bytes_rx[!s->side] > s->bytes_tx[!s->side]
|
||||
|| (s->eof_rx[!s->side] && !s->eof_tx[!s->side])
|
||||
)
|
||||
|
@ -9291,6 +9362,10 @@ sense_handler (int fd, unsigned char * sensed_data, void *arg)
|
|||
DBG (5, "Medium error: Carrier sheet\n");
|
||||
return SANE_STATUS_JAMMED;
|
||||
}
|
||||
if (0x0c == ascq) {
|
||||
DBG (5, "Medium error: ADF blocked by card\n");
|
||||
return SANE_STATUS_JAMMED;
|
||||
}
|
||||
if (0x10 == ascq) {
|
||||
DBG (5, "Medium error: no ink cartridge\n");
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
|
@ -10092,7 +10167,9 @@ buffer_deskew(struct fujitsu *s, int side)
|
|||
DBG (10, "buffer_deskew: start\n");
|
||||
|
||||
/*only find skew on first image from a page, or if first image had error */
|
||||
if(s->side == SIDE_FRONT || s->source == SOURCE_ADF_BACK || s->deskew_stat){
|
||||
if(s->side == SIDE_FRONT
|
||||
|| s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK
|
||||
|| s->deskew_stat){
|
||||
|
||||
s->deskew_stat = sanei_magic_findSkew(
|
||||
&s->s_params,s->buffers[side],s->resolution_x,s->resolution_y,
|
||||
|
|
|
@ -255,3 +255,6 @@ usb 0x04c5 0x1522
|
|||
|
||||
#ScanSnap iX1500
|
||||
usb 0x04c5 0x159f
|
||||
|
||||
#fi-800R
|
||||
usb 0x04c5 0x15fc
|
||||
|
|
|
@ -112,6 +112,7 @@ enum fujitsu_Option
|
|||
OPT_HOPPER,
|
||||
OPT_OMR,
|
||||
OPT_ADF_OPEN,
|
||||
OPT_CARD_LOADED,
|
||||
OPT_SLEEP,
|
||||
OPT_SEND_SW,
|
||||
OPT_MANUAL_FEED,
|
||||
|
@ -277,6 +278,7 @@ struct fujitsu
|
|||
int has_comp_JPG2;
|
||||
int has_comp_JPG3;
|
||||
int has_op_halt;
|
||||
int has_return_path;
|
||||
|
||||
/*FIXME: more endorser data? */
|
||||
int endorser_type_f;
|
||||
|
@ -361,7 +363,7 @@ struct fujitsu
|
|||
|
||||
/*mode group*/
|
||||
SANE_String_Const mode_list[7];
|
||||
SANE_String_Const source_list[5];
|
||||
SANE_String_Const source_list[8];
|
||||
|
||||
SANE_Int res_list[17];
|
||||
SANE_Range res_range;
|
||||
|
@ -599,6 +601,7 @@ struct fujitsu
|
|||
int hw_hopper;
|
||||
int hw_omr;
|
||||
int hw_adf_open;
|
||||
int hw_card_loaded;
|
||||
|
||||
int hw_sleep;
|
||||
int hw_send_sw;
|
||||
|
@ -618,7 +621,7 @@ struct fujitsu
|
|||
int hw_density_sw;
|
||||
|
||||
/* values which are used to track the frontend's access to sensors */
|
||||
char hw_read[NUM_OPTIONS-OPT_TOP];
|
||||
char hw_data_avail[NUM_OPTIONS-OPT_TOP];
|
||||
};
|
||||
|
||||
#define CONNECTION_SCSI 0 /* SCSI interface */
|
||||
|
@ -631,6 +634,9 @@ struct fujitsu
|
|||
#define SOURCE_ADF_FRONT 1
|
||||
#define SOURCE_ADF_BACK 2
|
||||
#define SOURCE_ADF_DUPLEX 3
|
||||
#define SOURCE_CARD_FRONT 4
|
||||
#define SOURCE_CARD_BACK 5
|
||||
#define SOURCE_CARD_DUPLEX 6
|
||||
|
||||
#define COMP_NONE WD_cmp_NONE
|
||||
#define COMP_JPEG WD_cmp_JPG1
|
||||
|
|
|
@ -124,15 +124,24 @@ usb 0x03f0 0x4605
|
|||
# Plustek OpticBook 3600
|
||||
usb 0x07b3 0x0900
|
||||
|
||||
# Plustek OpticFilm 7200
|
||||
usb 0x07b3 0x0807
|
||||
|
||||
# Plustek OpticFilm 7200i
|
||||
usb 0x07b3 0x0c04
|
||||
|
||||
# Plustek OpticFilm 7300
|
||||
usb 0x07b3 0x0c12
|
||||
|
||||
# Plustek OpticFilm 7400
|
||||
usb 0x07b3 0x0c3a
|
||||
|
||||
# Plustek OpticFilm 7500i
|
||||
usb 0x07b3 0x0c13
|
||||
|
||||
# Plustek OpticFilm 8200i
|
||||
usb 0x07b3 0x130d
|
||||
|
||||
# Primax Electronics, Ltd Xerox 2400 Onetouch
|
||||
usb 0x0461 0x038b
|
||||
|
||||
|
|
|
@ -63,8 +63,7 @@ struct Genesys_Calibration_Cache
|
|||
Genesys_Frontend frontend;
|
||||
Genesys_Sensor sensor;
|
||||
|
||||
size_t calib_pixels = 0;
|
||||
size_t calib_channels = 0;
|
||||
ScanSession session;
|
||||
size_t average_size = 0;
|
||||
std::vector<std::uint16_t> white_average_data;
|
||||
std::vector<std::uint16_t> dark_average_data;
|
||||
|
@ -75,8 +74,7 @@ struct Genesys_Calibration_Cache
|
|||
last_calibration == other.last_calibration &&
|
||||
frontend == other.frontend &&
|
||||
sensor == other.sensor &&
|
||||
calib_pixels == other.calib_pixels &&
|
||||
calib_channels == other.calib_channels &&
|
||||
session == other.session &&
|
||||
average_size == other.average_size &&
|
||||
white_average_data == other.white_average_data &&
|
||||
dark_average_data == other.dark_average_data;
|
||||
|
@ -94,8 +92,7 @@ void serialize(Stream& str, Genesys_Calibration_Cache& x)
|
|||
serialize_newline(str);
|
||||
serialize(str, x.sensor);
|
||||
serialize_newline(str);
|
||||
serialize(str, x.calib_pixels);
|
||||
serialize(str, x.calib_channels);
|
||||
serialize(str, x.session);
|
||||
serialize(str, x.average_size);
|
||||
serialize_newline(str);
|
||||
serialize(str, x.white_average_data);
|
||||
|
|
|
@ -67,14 +67,12 @@ public:
|
|||
virtual void init(Genesys_Device* dev) const = 0;
|
||||
|
||||
virtual void init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* regs, int* channels,
|
||||
int* total_size) const = 0;
|
||||
Genesys_Register_Set* regs) const = 0;
|
||||
|
||||
virtual void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const = 0;
|
||||
virtual void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const = 0;
|
||||
virtual void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const = 0;
|
||||
virtual void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const = 0;
|
||||
|
||||
/** Set up registers for a scan. Similar to init_regs_for_scan except that the session is
|
||||
already computed from the session
|
||||
|
@ -98,7 +96,6 @@ public:
|
|||
*/
|
||||
virtual void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const = 0;
|
||||
|
||||
virtual void search_start_position(Genesys_Device* dev) const = 0;
|
||||
virtual void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const = 0;
|
||||
virtual void coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
|
@ -134,11 +131,6 @@ public:
|
|||
|
||||
/// eject document from scanner
|
||||
virtual void eject_document(Genesys_Device* dev) const = 0;
|
||||
/**
|
||||
* search for an black or white area in forward or reverse
|
||||
* direction */
|
||||
virtual void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
bool forward, bool black) const = 0;
|
||||
|
||||
/// move scanning head to transparency adapter
|
||||
virtual void move_to_ta(Genesys_Device* dev) const = 0;
|
||||
|
@ -159,6 +151,16 @@ public:
|
|||
|
||||
/// cold boot init function
|
||||
virtual void asic_boot(Genesys_Device* dev, bool cold) const = 0;
|
||||
|
||||
/// checks if specific scan head is at home position
|
||||
virtual bool is_head_home(Genesys_Device& dev, ScanHeadId scan_head) const = 0;
|
||||
|
||||
/// enables or disables XPA slider motor
|
||||
virtual void set_xpa_lamp_power(Genesys_Device& dev, bool set) const = 0;
|
||||
|
||||
/// enables or disables XPA slider motor
|
||||
virtual void set_motor_mode(Genesys_Device& dev, Genesys_Register_Set& regs,
|
||||
MotorMode mode) const = 0;
|
||||
};
|
||||
|
||||
} // namespace genesys
|
||||
|
|
|
@ -0,0 +1,247 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
|
||||
#include "command_set_common.h"
|
||||
#include "low.h"
|
||||
#include "value_filter.h"
|
||||
|
||||
namespace genesys {
|
||||
|
||||
CommandSetCommon::~CommandSetCommon() = default;
|
||||
|
||||
bool CommandSetCommon::is_head_home(Genesys_Device& dev, ScanHeadId scan_head) const
|
||||
{
|
||||
struct HeadSettings {
|
||||
ModelId model_id;
|
||||
ScanHeadId scan_head;
|
||||
GenesysRegisterSettingSet regs;
|
||||
};
|
||||
|
||||
HeadSettings settings[] = {
|
||||
{ ModelId::CANON_8600F,
|
||||
ScanHeadId::PRIMARY, {
|
||||
{ 0x6c, 0x20, 0x60 },
|
||||
{ 0xa6, 0x00, 0x01 },
|
||||
}
|
||||
},
|
||||
{ ModelId::CANON_8600F,
|
||||
ScanHeadId::SECONDARY, {
|
||||
{ 0x6c, 0x00, 0x60 },
|
||||
{ 0xa6, 0x01, 0x01 },
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
for (const auto& setting : settings) {
|
||||
if (setting.model_id == dev.model->model_id &&
|
||||
setting.scan_head == scan_head)
|
||||
{
|
||||
auto reg_backup = apply_reg_settings_to_device_with_backup(dev, setting.regs);
|
||||
auto status = scanner_read_status(dev);
|
||||
apply_reg_settings_to_device(dev, reg_backup);
|
||||
return status.is_at_home;
|
||||
}
|
||||
}
|
||||
|
||||
auto status = scanner_read_status(dev);
|
||||
return status.is_at_home;
|
||||
}
|
||||
|
||||
void CommandSetCommon::set_xpa_lamp_power(Genesys_Device& dev, bool set) const
|
||||
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
|
||||
struct LampSettings {
|
||||
ModelId model_id;
|
||||
ScanMethod scan_method;
|
||||
GenesysRegisterSettingSet regs_on;
|
||||
GenesysRegisterSettingSet regs_off;
|
||||
};
|
||||
|
||||
// FIXME: BUG: we're not clearing the registers to the previous state when returning back when
|
||||
// turning off the lamp
|
||||
LampSettings settings[] = {
|
||||
{ ModelId::CANON_4400F, ScanMethod::TRANSPARENCY, {}, {} },
|
||||
{ ModelId::CANON_8400F, ScanMethod::TRANSPARENCY, {
|
||||
{ 0xa6, 0x34, 0xf4 },
|
||||
}, {
|
||||
{ 0xa6, 0x40, 0x70 },
|
||||
}
|
||||
},
|
||||
{ ModelId::CANON_8400F, ScanMethod::TRANSPARENCY_INFRARED, {
|
||||
{ 0x6c, 0x40, 0x40 },
|
||||
{ 0xa6, 0x01, 0xff },
|
||||
}, {
|
||||
{ 0x6c, 0x00, 0x40 },
|
||||
{ 0xa6, 0x00, 0xff },
|
||||
}
|
||||
},
|
||||
{ ModelId::CANON_8600F, ScanMethod::TRANSPARENCY, {
|
||||
{ 0xa6, 0x34, 0xf4 },
|
||||
{ 0xa7, 0xe0, 0xe0 },
|
||||
}, {
|
||||
{ 0xa6, 0x40, 0x70 },
|
||||
}
|
||||
},
|
||||
{ ModelId::CANON_8600F, ScanMethod::TRANSPARENCY_INFRARED, {
|
||||
{ 0xa6, 0x00, 0xc0 },
|
||||
{ 0xa7, 0xe0, 0xe0 },
|
||||
{ 0x6c, 0x80, 0x80 },
|
||||
}, {
|
||||
{ 0xa6, 0x00, 0xc0 },
|
||||
{ 0x6c, 0x00, 0x80 },
|
||||
}
|
||||
},
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7200, ScanMethod::TRANSPARENCY, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7200I, ScanMethod::TRANSPARENCY, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7200I, ScanMethod::TRANSPARENCY_INFRARED, {
|
||||
{ 0xa8, 0x07, 0x07 },
|
||||
}, {
|
||||
{ 0xa8, 0x00, 0x07 },
|
||||
}
|
||||
},
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7300, ScanMethod::TRANSPARENCY, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7400, ScanMethod::TRANSPARENCY, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7500I, ScanMethod::TRANSPARENCY, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7500I, ScanMethod::TRANSPARENCY_INFRARED, {
|
||||
{ 0xa8, 0x07, 0x07 },
|
||||
}, {
|
||||
{ 0xa8, 0x00, 0x07 },
|
||||
}
|
||||
},
|
||||
{ ModelId::PLUSTEK_OPTICFILM_8200I, ScanMethod::TRANSPARENCY, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_8200I, ScanMethod::TRANSPARENCY_INFRARED, {
|
||||
{ 0xa8, 0x04, 0x04 },
|
||||
}, {
|
||||
{ 0xa8, 0x00, 0x04 },
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
for (const auto& setting : settings) {
|
||||
if (setting.model_id == dev.model->model_id &&
|
||||
setting.scan_method == dev.settings.scan_method)
|
||||
{
|
||||
apply_reg_settings_to_device(dev, set ? setting.regs_on : setting.regs_off);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw SaneException("Could not find XPA lamp settings");
|
||||
}
|
||||
|
||||
|
||||
void CommandSetCommon::set_motor_mode(Genesys_Device& dev, Genesys_Register_Set& regs,
|
||||
MotorMode mode) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
|
||||
struct MotorSettings {
|
||||
ModelId model_id;
|
||||
ValueFilterAny<unsigned> resolutions;
|
||||
GenesysRegisterSettingSet regs_primary_and_secondary;
|
||||
GenesysRegisterSettingSet regs_primary;
|
||||
GenesysRegisterSettingSet regs_secondary;
|
||||
};
|
||||
|
||||
MotorSettings settings[] = {
|
||||
{ ModelId::CANON_8400F, { 400, 800, 1600, 3200 }, {
|
||||
{ 0x6c, 0x00, 0x90 },
|
||||
{ 0xa9, 0x04, 0x06 },
|
||||
}, {
|
||||
{ 0x6c, 0x90, 0x90 },
|
||||
{ 0xa9, 0x02, 0x06 },
|
||||
}, {}
|
||||
},
|
||||
{ ModelId::CANON_8600F, { 300, 600, 1200 }, {
|
||||
{ 0x6c, 0x00, 0x60 },
|
||||
{ 0xa6, 0x01, 0x41 },
|
||||
}, {
|
||||
{ 0x6c, 0x20, 0x62 },
|
||||
{ 0xa6, 0x00, 0x41 },
|
||||
}, {
|
||||
{ 0x6c, 0x40, 0x62 },
|
||||
{ 0xa6, 0x01, 0x41 },
|
||||
}
|
||||
},
|
||||
{ ModelId::CANON_8600F, { 2400, 4800 }, {
|
||||
{ 0x6c, 0x02, 0x62 },
|
||||
{ 0xa6, 0x01, 0x41 },
|
||||
}, {
|
||||
{ 0x6c, 0x20, 0x62 },
|
||||
{ 0xa6, 0x00, 0x41 },
|
||||
}, {
|
||||
{ 0x6c, 0x40, 0x62 },
|
||||
{ 0xa6, 0x01, 0x41 },
|
||||
}
|
||||
},
|
||||
{ ModelId::HP_SCANJET_G4050, VALUE_FILTER_ANY, {
|
||||
{ 0x6b, 0x81, 0x81 }, // set MULTFILM and GPOADF
|
||||
{ 0x6c, 0x00, 0x40 }, // note that reverse change is not applied on off
|
||||
// 0xa6 register 0x08 bit likely sets motor power. No move at all without that one
|
||||
{ 0xa6, 0x08, 0x08 }, // note that reverse change is not applied on off
|
||||
{ 0xa8, 0x00, 0x04 },
|
||||
{ 0xa9, 0x30, 0x30 },
|
||||
}, {
|
||||
{ 0x6b, 0x00, 0x01 }, // BUG: note that only ADF is unset
|
||||
{ 0xa8, 0x04, 0x04 },
|
||||
{ 0xa9, 0x00, 0x10 }, // note that 0x20 bit is not reset
|
||||
}, {}
|
||||
},
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7200, VALUE_FILTER_ANY, {}, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7200I, VALUE_FILTER_ANY, {}, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7300, VALUE_FILTER_ANY, {}, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7400, VALUE_FILTER_ANY, {}, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7500I, VALUE_FILTER_ANY, {}, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_8200I, VALUE_FILTER_ANY, {}, {}, {} },
|
||||
};
|
||||
|
||||
for (const auto& setting : settings) {
|
||||
if (setting.model_id == dev.model->model_id &&
|
||||
setting.resolutions.matches(dev.session.output_resolution))
|
||||
{
|
||||
switch (mode) {
|
||||
case MotorMode::PRIMARY: {
|
||||
apply_reg_settings_to_device(dev, setting.regs_primary);
|
||||
break;
|
||||
}
|
||||
case MotorMode::PRIMARY_AND_SECONDARY: {
|
||||
apply_reg_settings_to_device(dev, setting.regs_primary_and_secondary);
|
||||
break;
|
||||
}
|
||||
case MotorMode::SECONDARY: {
|
||||
apply_reg_settings_to_device(dev, setting.regs_secondary);
|
||||
break;
|
||||
}
|
||||
}
|
||||
regs.state.motor_mode = mode;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw SaneException("Motor settings have not been found");
|
||||
}
|
||||
|
||||
} // namespace genesys
|
|
@ -0,0 +1,48 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef BACKEND_GENESYS_COMMAND_SET_COMMON_H
|
||||
#define BACKEND_GENESYS_COMMAND_SET_COMMON_H
|
||||
|
||||
#include "command_set.h"
|
||||
|
||||
namespace genesys {
|
||||
|
||||
|
||||
/** Common command set functionality
|
||||
*/
|
||||
class CommandSetCommon : public CommandSet
|
||||
{
|
||||
public:
|
||||
~CommandSetCommon() override;
|
||||
|
||||
bool is_head_home(Genesys_Device& dev, ScanHeadId scan_head) const override;
|
||||
|
||||
void set_xpa_lamp_power(Genesys_Device& dev, bool set) const override;
|
||||
|
||||
void set_motor_mode(Genesys_Device& dev, Genesys_Register_Set& regs,
|
||||
MotorMode mode) const override;
|
||||
};
|
||||
|
||||
} // namespace genesys
|
||||
|
||||
#endif // BACKEND_GENESYS_COMMAND_SET_COMMON_H
|
|
@ -146,9 +146,7 @@ void genesys_gray_lineart(Genesys_Device* dev,
|
|||
{
|
||||
DBG_HELPER(dbg);
|
||||
std::size_t y;
|
||||
|
||||
DBG(DBG_io2, "%s: converting %zu lines of %zu pixels\n", __func__, lines, pixels);
|
||||
DBG(DBG_io2, "%s: threshold=%d\n", __func__, threshold);
|
||||
(void) threshold;
|
||||
|
||||
for (y = 0; y < lines; y++)
|
||||
{
|
||||
|
@ -200,7 +198,7 @@ void genesys_deskew(Genesys_Scanner *s, const Genesys_Sensor& sensor)
|
|||
bg=0xff;
|
||||
}
|
||||
TIE(sanei_magic_findSkew(&s->params, dev->img_buffer.data(),
|
||||
sensor.optical_res, sensor.optical_res,
|
||||
sensor.full_resolution, sensor.full_resolution,
|
||||
&x, &y, &slope));
|
||||
|
||||
DBG(DBG_info, "%s: slope=%f => %f\n", __func__, slope, slope * 180 / M_PI);
|
||||
|
|
|
@ -62,15 +62,24 @@ std::vector<unsigned> MethodResolutions::get_resolutions() const
|
|||
return ret;
|
||||
}
|
||||
|
||||
const MethodResolutions& Genesys_Model::get_resolution_settings(ScanMethod method) const
|
||||
const MethodResolutions* Genesys_Model::get_resolution_settings_ptr(ScanMethod method) const
|
||||
{
|
||||
for (const auto& res_for_method : resolutions) {
|
||||
for (auto res_method : res_for_method.methods) {
|
||||
if (res_method == method) {
|
||||
return res_for_method;
|
||||
return &res_for_method;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
const MethodResolutions& Genesys_Model::get_resolution_settings(ScanMethod method) const
|
||||
{
|
||||
const auto* ptr = get_resolution_settings_ptr(method);
|
||||
if (ptr)
|
||||
return *ptr;
|
||||
|
||||
throw SaneException("Could not find resolution settings for method %d",
|
||||
static_cast<unsigned>(method));
|
||||
}
|
||||
|
@ -80,6 +89,12 @@ std::vector<unsigned> Genesys_Model::get_resolutions(ScanMethod method) const
|
|||
return get_resolution_settings(method).get_resolutions();
|
||||
}
|
||||
|
||||
bool Genesys_Model::has_method(ScanMethod method) const
|
||||
{
|
||||
return get_resolution_settings_ptr(method) != nullptr;
|
||||
}
|
||||
|
||||
|
||||
Genesys_Device::~Genesys_Device()
|
||||
{
|
||||
clear();
|
||||
|
@ -124,10 +139,14 @@ unsigned Genesys_Device::head_pos(ScanHeadId scan_head) const
|
|||
}
|
||||
}
|
||||
|
||||
void Genesys_Device::set_head_pos_unknown()
|
||||
void Genesys_Device::set_head_pos_unknown(ScanHeadId scan_head)
|
||||
{
|
||||
is_head_pos_primary_known_ = false;
|
||||
is_head_pos_secondary_known_ = false;
|
||||
if ((scan_head & ScanHeadId::PRIMARY) != ScanHeadId::NONE) {
|
||||
is_head_pos_primary_known_ = false;
|
||||
}
|
||||
if ((scan_head & ScanHeadId::SECONDARY) != ScanHeadId::NONE) {
|
||||
is_head_pos_secondary_known_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Genesys_Device::set_head_pos_zero(ScanHeadId scan_head)
|
||||
|
@ -205,12 +224,15 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev)
|
|||
<< " ignore_offsets: " << dev.ignore_offsets << '\n'
|
||||
<< " model: (not printed)\n"
|
||||
<< " reg: " << format_indent_braced_list(4, dev.reg) << '\n'
|
||||
<< " calib_reg: " << format_indent_braced_list(4, dev.calib_reg) << '\n'
|
||||
<< " initial_regs: " << format_indent_braced_list(4, dev.initial_regs) << '\n'
|
||||
<< " settings: " << format_indent_braced_list(4, dev.settings) << '\n'
|
||||
<< " frontend: " << format_indent_braced_list(4, dev.frontend) << '\n'
|
||||
<< " frontend_initial: " << format_indent_braced_list(4, dev.frontend_initial) << '\n'
|
||||
<< " frontend_is_init: " << dev.frontend_is_init << '\n'
|
||||
<< " gpo.regs: " << format_indent_braced_list(4, dev.gpo.regs) << '\n'
|
||||
<< " frontend_initial: " << format_indent_braced_list(4, dev.frontend_initial) << '\n';
|
||||
if (!dev.memory_layout.regs.empty()) {
|
||||
out << " memory_layout.regs: "
|
||||
<< format_indent_braced_list(4, dev.memory_layout.regs) << '\n';
|
||||
}
|
||||
out << " gpo.regs: " << format_indent_braced_list(4, dev.gpo.regs) << '\n'
|
||||
<< " motor: " << format_indent_braced_list(4, dev.motor) << '\n'
|
||||
<< " control[0..6]: " << std::hex
|
||||
<< static_cast<unsigned>(dev.control[0]) << ' '
|
||||
|
@ -220,13 +242,7 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev)
|
|||
<< static_cast<unsigned>(dev.control[4]) << ' '
|
||||
<< static_cast<unsigned>(dev.control[5]) << '\n' << std::dec
|
||||
<< " average_size: " << dev.average_size << '\n'
|
||||
<< " calib_pixels: " << dev.calib_pixels << '\n'
|
||||
<< " calib_lines: " << dev.calib_lines << '\n'
|
||||
<< " calib_channels: " << dev.calib_channels << '\n'
|
||||
<< " calib_resolution: " << dev.calib_resolution << '\n'
|
||||
<< " calib_total_bytes_to_read: " << dev.calib_total_bytes_to_read << '\n'
|
||||
<< " calib_session: " << format_indent_braced_list(4, dev.calib_session) << '\n'
|
||||
<< " calib_pixels_offset: " << dev.calib_pixels_offset << '\n'
|
||||
<< " gamma_override_tables[0].size(): " << dev.gamma_override_tables[0].size() << '\n'
|
||||
<< " gamma_override_tables[1].size(): " << dev.gamma_override_tables[1].size() << '\n'
|
||||
<< " gamma_override_tables[2].size(): " << dev.gamma_override_tables[2].size() << '\n'
|
||||
|
@ -260,13 +276,36 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev)
|
|||
return out;
|
||||
}
|
||||
|
||||
void apply_reg_settings_to_device(Genesys_Device& dev, const GenesysRegisterSettingSet& regs)
|
||||
void apply_reg_settings_to_device_write_only(Genesys_Device& dev,
|
||||
const GenesysRegisterSettingSet& regs)
|
||||
{
|
||||
GenesysRegisterSettingSet backup;
|
||||
for (const auto& reg : regs) {
|
||||
uint8_t val = dev.interface->read_register(reg.address);
|
||||
val = (val & ~reg.mask) | (reg.value & reg.mask);
|
||||
dev.interface->write_register(reg.address, val);
|
||||
dev.interface->write_register(reg.address, reg.value);
|
||||
}
|
||||
}
|
||||
|
||||
void apply_reg_settings_to_device(Genesys_Device& dev, const GenesysRegisterSettingSet& regs)
|
||||
{
|
||||
apply_reg_settings_to_device_with_backup(dev, regs);
|
||||
}
|
||||
|
||||
GenesysRegisterSettingSet
|
||||
apply_reg_settings_to_device_with_backup(Genesys_Device& dev,
|
||||
const GenesysRegisterSettingSet& regs)
|
||||
{
|
||||
GenesysRegisterSettingSet backup;
|
||||
for (const auto& reg : regs) {
|
||||
std::uint8_t old_val = dev.interface->read_register(reg.address);
|
||||
std::uint8_t new_val = (old_val & ~reg.mask) | (reg.value & reg.mask);
|
||||
dev.interface->write_register(reg.address, new_val);
|
||||
|
||||
using SettingType = GenesysRegisterSettingSet::SettingType;
|
||||
backup.push_back(SettingType{reg.address,
|
||||
static_cast<std::uint8_t>(old_val & reg.mask),
|
||||
reg.mask});
|
||||
}
|
||||
return backup;
|
||||
}
|
||||
|
||||
} // namespace genesys
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "register.h"
|
||||
#include "usb_device.h"
|
||||
#include "scanner_interface.h"
|
||||
#include "utilities.h"
|
||||
#include <vector>
|
||||
|
||||
namespace genesys {
|
||||
|
@ -77,22 +78,15 @@ struct Genesys_Gpo
|
|||
GenesysRegisterSettingSet regs;
|
||||
};
|
||||
|
||||
/// Stores a SANE_Fixed value which is automatically converted from and to floating-point values
|
||||
class FixedFloat
|
||||
struct MemoryLayout
|
||||
{
|
||||
public:
|
||||
FixedFloat() = default;
|
||||
FixedFloat(const FixedFloat&) = default;
|
||||
FixedFloat(double number) : value_{SANE_FIX(number)} {}
|
||||
FixedFloat& operator=(const FixedFloat&) = default;
|
||||
FixedFloat& operator=(double number) { value_ = SANE_FIX(number); return *this; }
|
||||
// This is used on GL845, GL846, GL847 and GL124 which have special registers to define the
|
||||
// memory layout
|
||||
MemoryLayout() = default;
|
||||
|
||||
operator double() const { return value(); }
|
||||
ValueFilter<ModelId> models;
|
||||
|
||||
double value() const { return SANE_UNFIX(value_); }
|
||||
|
||||
private:
|
||||
SANE_Fixed value_ = 0;
|
||||
GenesysRegisterSettingSet regs;
|
||||
};
|
||||
|
||||
struct MethodResolutions
|
||||
|
@ -106,6 +100,16 @@ struct MethodResolutions
|
|||
return *std::min_element(resolutions_x.begin(), resolutions_x.end());
|
||||
}
|
||||
|
||||
unsigned get_nearest_resolution_x(unsigned resolution) const
|
||||
{
|
||||
return *std::min_element(resolutions_x.begin(), resolutions_x.end(),
|
||||
[&](unsigned lhs, unsigned rhs)
|
||||
{
|
||||
return std::abs(static_cast<int>(lhs) - static_cast<int>(resolution)) <
|
||||
std::abs(static_cast<int>(rhs) - static_cast<int>(resolution));
|
||||
});
|
||||
}
|
||||
|
||||
unsigned get_min_resolution_y() const
|
||||
{
|
||||
return *std::min_element(resolutions_y.begin(), resolutions_y.end());
|
||||
|
@ -143,51 +147,67 @@ struct Genesys_Model
|
|||
// All offsets below are with respect to the sensor home position
|
||||
|
||||
// Start of scan area in mm
|
||||
FixedFloat x_offset = 0;
|
||||
float x_offset = 0;
|
||||
|
||||
// Start of scan area in mm (Amount of feeding needed to get to the medium)
|
||||
FixedFloat y_offset = 0;
|
||||
float y_offset = 0;
|
||||
|
||||
// Size of scan area in mm
|
||||
FixedFloat x_size = 0;
|
||||
float x_size = 0;
|
||||
|
||||
// Size of scan area in mm
|
||||
FixedFloat y_size = 0;
|
||||
float y_size = 0;
|
||||
|
||||
// Start of white strip in mm
|
||||
FixedFloat y_offset_calib_white = 0;
|
||||
// Start of white strip in mm for scanners that use separate dark and white shading calibration.
|
||||
float y_offset_calib_white = 0;
|
||||
|
||||
// The size of the scan area that is used to acquire shading data in mm
|
||||
float y_size_calib_mm = 0;
|
||||
|
||||
// Start of the black/white strip in mm for scanners that use unified dark and white shading
|
||||
// calibration.
|
||||
float y_offset_calib_dark_white_mm = 0;
|
||||
|
||||
// The size of the scan area that is used to acquire dark/white shading data in mm
|
||||
float y_size_calib_dark_white_mm = 0;
|
||||
|
||||
// The width of the scan area that is used to acquire shading data
|
||||
float x_size_calib_mm = 0;
|
||||
|
||||
// Start of black mark in mm
|
||||
FixedFloat x_offset_calib_black = 0;
|
||||
float x_offset_calib_black = 0;
|
||||
|
||||
// Start of scan area in transparency mode in mm
|
||||
FixedFloat x_offset_ta = 0;
|
||||
float x_offset_ta = 0;
|
||||
|
||||
// Start of scan area in transparency mode in mm
|
||||
FixedFloat y_offset_ta = 0;
|
||||
float y_offset_ta = 0;
|
||||
|
||||
// Size of scan area in transparency mode in mm
|
||||
FixedFloat x_size_ta = 0;
|
||||
float x_size_ta = 0;
|
||||
|
||||
// Size of scan area in transparency mode in mm
|
||||
FixedFloat y_size_ta = 0;
|
||||
float y_size_ta = 0;
|
||||
|
||||
// The position of the sensor when it's aligned with the lamp for transparency scanning
|
||||
FixedFloat y_offset_sensor_to_ta = 0;
|
||||
float y_offset_sensor_to_ta = 0;
|
||||
|
||||
// Start of white strip in transparency mode in mm
|
||||
FixedFloat y_offset_calib_white_ta = 0;
|
||||
float y_offset_calib_white_ta = 0;
|
||||
|
||||
// Start of black strip in transparency mode in mm
|
||||
FixedFloat y_offset_calib_black_ta = 0;
|
||||
float y_offset_calib_black_ta = 0;
|
||||
|
||||
// The size of the scan area that is used to acquire shading data in transparency mode in mm
|
||||
float y_size_calib_ta_mm = 0;
|
||||
|
||||
// Size of scan area after paper sensor stop sensing document in mm
|
||||
FixedFloat post_scan = 0;
|
||||
float post_scan = 0;
|
||||
|
||||
// Amount of feeding needed to eject document after finishing scanning in mm
|
||||
FixedFloat eject_feed = 0;
|
||||
float eject_feed = 0;
|
||||
|
||||
// Line-distance correction (in pixel at optical_ydpi) for CCD scanners
|
||||
// Line-distance correction (in pixel at motor base_ydpi) for CCD scanners
|
||||
SANE_Int ld_shift_r = 0;
|
||||
SANE_Int ld_shift_g = 0;
|
||||
SANE_Int ld_shift_b = 0;
|
||||
|
@ -210,22 +230,24 @@ struct Genesys_Model
|
|||
// stepper motor type
|
||||
MotorId motor_id = MotorId::UNKNOWN;
|
||||
|
||||
// Which hacks are needed for this scanner?
|
||||
SANE_Word flags = 0;
|
||||
// Which customizations are needed for this scanner?
|
||||
ModelFlag flags = ModelFlag::NONE;
|
||||
|
||||
// Button flags, described existing buttons for the model
|
||||
SANE_Word buttons = 0;
|
||||
|
||||
// how many lines are used for shading calibration
|
||||
SANE_Int shading_lines = 0;
|
||||
// how many lines are used for shading calibration in TA mode
|
||||
SANE_Int shading_ta_lines = 0;
|
||||
// how many lines are used to search start position
|
||||
SANE_Int search_lines = 0;
|
||||
|
||||
// returns nullptr if method is not supported
|
||||
const MethodResolutions* get_resolution_settings_ptr(ScanMethod method) const;
|
||||
|
||||
// throws if method is not supported
|
||||
const MethodResolutions& get_resolution_settings(ScanMethod method) const;
|
||||
|
||||
std::vector<unsigned> get_resolutions(ScanMethod method) const;
|
||||
|
||||
bool has_method(ScanMethod method) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -243,8 +265,8 @@ struct Genesys_Device
|
|||
// frees commonly used data
|
||||
void clear();
|
||||
|
||||
SANE_Word vendorId = 0; /**< USB vendor identifier */
|
||||
SANE_Word productId = 0; /**< USB product identifier */
|
||||
std::uint16_t vendorId = 0; // USB vendor identifier
|
||||
std::uint16_t productId = 0; // USB product identifier
|
||||
|
||||
// USB mode:
|
||||
// 0: not set
|
||||
|
@ -261,42 +283,25 @@ struct Genesys_Device
|
|||
// acquiring the positions of the black and white strips and the actual scan area
|
||||
bool ignore_offsets = false;
|
||||
|
||||
Genesys_Model *model = nullptr;
|
||||
const Genesys_Model* model = nullptr;
|
||||
|
||||
// pointers to low level functions
|
||||
std::unique_ptr<CommandSet> cmd_set;
|
||||
|
||||
Genesys_Register_Set reg;
|
||||
Genesys_Register_Set calib_reg;
|
||||
Genesys_Register_Set initial_regs;
|
||||
Genesys_Settings settings;
|
||||
Genesys_Frontend frontend, frontend_initial;
|
||||
|
||||
// whether the frontend is initialized. This is currently used just to preserve historical
|
||||
// behavior
|
||||
bool frontend_is_init = false;
|
||||
|
||||
Genesys_Gpo gpo;
|
||||
MemoryLayout memory_layout;
|
||||
Genesys_Motor motor;
|
||||
std::uint8_t control[6] = {};
|
||||
|
||||
size_t average_size = 0;
|
||||
// number of pixels used during shading calibration
|
||||
size_t calib_pixels = 0;
|
||||
// number of lines used during shading calibration
|
||||
size_t calib_lines = 0;
|
||||
size_t calib_channels = 0;
|
||||
size_t calib_resolution = 0;
|
||||
// bytes to read from USB when calibrating. If 0, this is not set
|
||||
size_t calib_total_bytes_to_read = 0;
|
||||
|
||||
// the session that was configured for calibration
|
||||
ScanSession calib_session;
|
||||
|
||||
// certain scanners support much higher resolution when scanning transparency, but we can't
|
||||
// read whole width of the scanner as a single line at that resolution. Thus for stuff like
|
||||
// calibration we want to read only the possible calibration area.
|
||||
size_t calib_pixels_offset = 0;
|
||||
|
||||
// gamma overrides. If a respective array is not empty then it means that the gamma for that
|
||||
// color is overridden.
|
||||
std::vector<std::uint16_t> gamma_override_tables[3];
|
||||
|
@ -360,7 +365,7 @@ struct Genesys_Device
|
|||
|
||||
bool is_head_pos_known(ScanHeadId scan_head) const;
|
||||
unsigned head_pos(ScanHeadId scan_head) const;
|
||||
void set_head_pos_unknown();
|
||||
void set_head_pos_unknown(ScanHeadId scan_head);
|
||||
void set_head_pos_zero(ScanHeadId scan_head);
|
||||
void advance_head_pos_by_session(ScanHeadId scan_head);
|
||||
void advance_head_pos_by_steps(ScanHeadId scan_head, Direction direction, unsigned steps);
|
||||
|
@ -382,6 +387,12 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev);
|
|||
|
||||
void apply_reg_settings_to_device(Genesys_Device& dev, const GenesysRegisterSettingSet& regs);
|
||||
|
||||
void apply_reg_settings_to_device_write_only(Genesys_Device& dev,
|
||||
const GenesysRegisterSettingSet& regs);
|
||||
GenesysRegisterSettingSet
|
||||
apply_reg_settings_to_device_with_backup(Genesys_Device& dev,
|
||||
const GenesysRegisterSettingSet& regs);
|
||||
|
||||
} // namespace genesys
|
||||
|
||||
#endif
|
||||
|
|
|
@ -109,6 +109,188 @@ std::ostream& operator<<(std::ostream& out, ColorFilter mode)
|
|||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, ModelId id)
|
||||
{
|
||||
switch (id) {
|
||||
case ModelId::UNKNOWN: out << "UNKNOWN"; break;
|
||||
case ModelId::CANON_4400F: out << "CANON_4400F"; break;
|
||||
case ModelId::CANON_5600F: out << "CANON_5600F"; break;
|
||||
case ModelId::CANON_8400F: out << "CANON_8400F"; break;
|
||||
case ModelId::CANON_8600F: out << "CANON_8600F"; break;
|
||||
case ModelId::CANON_IMAGE_FORMULA_101: out << "CANON_IMAGE_FORMULA_101"; break;
|
||||
case ModelId::CANON_LIDE_50: out << "CANON_LIDE_50"; break;
|
||||
case ModelId::CANON_LIDE_60: out << "CANON_LIDE_60"; break;
|
||||
case ModelId::CANON_LIDE_80: out << "CANON_LIDE_80"; break;
|
||||
case ModelId::CANON_LIDE_100: out << "CANON_LIDE_100"; break;
|
||||
case ModelId::CANON_LIDE_110: out << "CANON_LIDE_110"; break;
|
||||
case ModelId::CANON_LIDE_120: out << "CANON_LIDE_120"; break;
|
||||
case ModelId::CANON_LIDE_200: out << "CANON_LIDE_200"; break;
|
||||
case ModelId::CANON_LIDE_210: out << "CANON_LIDE_210"; break;
|
||||
case ModelId::CANON_LIDE_220: out << "CANON_LIDE_220"; break;
|
||||
case ModelId::CANON_LIDE_700F: out << "CANON_LIDE_700F"; break;
|
||||
case ModelId::DCT_DOCKETPORT_487: out << "DCT_DOCKETPORT_487"; break;
|
||||
case ModelId::HP_SCANJET_2300C: out << "HP_SCANJET_2300C"; break;
|
||||
case ModelId::HP_SCANJET_2400C: out << "HP_SCANJET_2400C"; break;
|
||||
case ModelId::HP_SCANJET_3670: out << "HP_SCANJET_3670"; break;
|
||||
case ModelId::HP_SCANJET_4850C: out << "HP_SCANJET_4850C"; break;
|
||||
case ModelId::HP_SCANJET_G4010: out << "HP_SCANJET_G4010"; break;
|
||||
case ModelId::HP_SCANJET_G4050: out << "HP_SCANJET_G4050"; break;
|
||||
case ModelId::HP_SCANJET_N6310: out << "HP_SCANJET_N6310"; break;
|
||||
case ModelId::MEDION_MD5345: out << "MEDION_MD5345"; break;
|
||||
case ModelId::PANASONIC_KV_SS080: out << "PANASONIC_KV_SS080"; break;
|
||||
case ModelId::PENTAX_DSMOBILE_600: out << "PENTAX_DSMOBILE_600"; break;
|
||||
case ModelId::PLUSTEK_OPTICBOOK_3800: out << "PLUSTEK_OPTICBOOK_3800"; break;
|
||||
case ModelId::PLUSTEK_OPTICFILM_7200: out << "PLUSTEK_OPTICFILM_7200"; break;
|
||||
case ModelId::PLUSTEK_OPTICFILM_7200I: out << "PLUSTEK_OPTICFILM_7200I"; break;
|
||||
case ModelId::PLUSTEK_OPTICFILM_7300: out << "PLUSTEK_OPTICFILM_7300"; break;
|
||||
case ModelId::PLUSTEK_OPTICFILM_7400: out << "PLUSTEK_OPTICFILM_7400"; break;
|
||||
case ModelId::PLUSTEK_OPTICFILM_7500I: out << "PLUSTEK_OPTICFILM_7500I"; break;
|
||||
case ModelId::PLUSTEK_OPTICFILM_8200I: out << "PLUSTEK_OPTICFILM_8200I"; break;
|
||||
case ModelId::PLUSTEK_OPTICPRO_3600: out << "PLUSTEK_OPTICPRO_3600"; break;
|
||||
case ModelId::PLUSTEK_OPTICPRO_ST12: out << "PLUSTEK_OPTICPRO_ST12"; break;
|
||||
case ModelId::PLUSTEK_OPTICPRO_ST24: out << "PLUSTEK_OPTICPRO_ST24"; break;
|
||||
case ModelId::SYSCAN_DOCKETPORT_465: out << "SYSCAN_DOCKETPORT_465"; break;
|
||||
case ModelId::SYSCAN_DOCKETPORT_467: out << "SYSCAN_DOCKETPORT_467"; break;
|
||||
case ModelId::SYSCAN_DOCKETPORT_485: out << "SYSCAN_DOCKETPORT_485"; break;
|
||||
case ModelId::SYSCAN_DOCKETPORT_665: out << "SYSCAN_DOCKETPORT_665"; break;
|
||||
case ModelId::SYSCAN_DOCKETPORT_685: out << "SYSCAN_DOCKETPORT_685"; break;
|
||||
case ModelId::UMAX_ASTRA_4500: out << "UMAX_ASTRA_4500"; break;
|
||||
case ModelId::VISIONEER_7100: out << "VISIONEER_7100"; break;
|
||||
case ModelId::VISIONEER_ROADWARRIOR: out << "VISIONEER_ROADWARRIOR"; break;
|
||||
case ModelId::VISIONEER_STROBE_XP100_REVISION3:
|
||||
out << "VISIONEER_STROBE_XP100_REVISION3"; break;
|
||||
case ModelId::VISIONEER_STROBE_XP200: out << "VISIONEER_STROBE_XP200"; break;
|
||||
case ModelId::VISIONEER_STROBE_XP300: out << "VISIONEER_STROBE_XP300"; break;
|
||||
case ModelId::XEROX_2400: out << "XEROX_2400"; break;
|
||||
case ModelId::XEROX_TRAVELSCANNER_100: out << "XEROX_TRAVELSCANNER_100"; break;
|
||||
default:
|
||||
out << static_cast<unsigned>(id); break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, AdcId id)
|
||||
{
|
||||
switch (id) {
|
||||
case AdcId::UNKNOWN: out << "UNKNOWN"; break;
|
||||
case AdcId::AD_XP200: out << "AD_XP200"; break;
|
||||
case AdcId::CANON_LIDE_35: out << "CANON_LIDE_35"; break;
|
||||
case AdcId::CANON_LIDE_80: out << "CANON_LIDE_80"; break;
|
||||
case AdcId::CANON_LIDE_110: out << "CANON_LIDE_110"; break;
|
||||
case AdcId::CANON_LIDE_120: out << "CANON_LIDE_120"; break;
|
||||
case AdcId::CANON_LIDE_200: out << "CANON_LIDE_200"; break;
|
||||
case AdcId::CANON_LIDE_700F: out << "CANON_LIDE_700F"; break;
|
||||
case AdcId::CANON_4400F: out << "CANON_4400F"; break;
|
||||
case AdcId::CANON_8400F: out << "CANON_8400F"; break;
|
||||
case AdcId::CANON_8600F: out << "CANON_8600F"; break;
|
||||
case AdcId::G4050: out << "G4050"; break;
|
||||
case AdcId::IMG101: out << "IMG101"; break;
|
||||
case AdcId::KVSS080: out << "KVSS080"; break;
|
||||
case AdcId::PLUSTEK_OPTICBOOK_3800: out << "PLUSTEK_OPTICBOOK_3800"; break;
|
||||
case AdcId::PLUSTEK_OPTICFILM_7200I: out << "PLUSTEK_OPTICFILM_7200I"; break;
|
||||
case AdcId::PLUSTEK_OPTICFILM_7300: out << "PLUSTEK_OPTICFILM_7300"; break;
|
||||
case AdcId::PLUSTEK_OPTICFILM_7400: out << "PLUSTEK_OPTICFILM_7400"; break;
|
||||
case AdcId::PLUSTEK_OPTICFILM_7500I: out << "PLUSTEK_OPTICFILM_7500I"; break;
|
||||
case AdcId::PLUSTEK_OPTICFILM_8200I: out << "PLUSTEK_OPTICFILM_8200I"; break;
|
||||
case AdcId::PLUSTEK_OPTICPRO_3600: out << "PLUSTEK_OPTICPRO_3600"; break;
|
||||
case AdcId::WOLFSON_5345: out << "WOLFSON_5345"; break;
|
||||
case AdcId::WOLFSON_DSM600: out << "WOLFSON_DSM600"; break;
|
||||
case AdcId::WOLFSON_HP2300: out << "WOLFSON_HP2300"; break;
|
||||
case AdcId::WOLFSON_HP2400: out << "WOLFSON_HP2400"; break;
|
||||
case AdcId::WOLFSON_HP3670: out << "WOLFSON_HP3670"; break;
|
||||
case AdcId::WOLFSON_ST12: out << "WOLFSON_ST12"; break;
|
||||
case AdcId::WOLFSON_ST24: out << "WOLFSON_ST24"; break;
|
||||
case AdcId::WOLFSON_UMAX: out << "WOLFSON_UMAX"; break;
|
||||
case AdcId::WOLFSON_XP300: out << "WOLFSON_XP300"; break;
|
||||
default:
|
||||
out << static_cast<unsigned>(id); break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, GpioId id)
|
||||
{
|
||||
switch (id) {
|
||||
case GpioId::UNKNOWN: out << "UNKNOWN"; break;
|
||||
case GpioId::CANON_LIDE_35: out << "CANON_LIDE_35"; break;
|
||||
case GpioId::CANON_LIDE_80: out << "CANON_LIDE_80"; break;
|
||||
case GpioId::CANON_LIDE_110: out << "CANON_LIDE_110"; break;
|
||||
case GpioId::CANON_LIDE_120: out << "CANON_LIDE_120"; break;
|
||||
case GpioId::CANON_LIDE_200: out << "CANON_LIDE_200"; break;
|
||||
case GpioId::CANON_LIDE_210: out << "CANON_LIDE_210"; break;
|
||||
case GpioId::CANON_LIDE_700F: out << "CANON_LIDE_700F"; break;
|
||||
case GpioId::CANON_4400F: out << "CANON_4400F"; break;
|
||||
case GpioId::CANON_8400F: out << "CANON_8400F"; break;
|
||||
case GpioId::CANON_8600F: out << "CANON_8600F"; break;
|
||||
case GpioId::DP665: out << "DP665"; break;
|
||||
case GpioId::DP685: out << "DP685"; break;
|
||||
case GpioId::G4050: out << "G4050"; break;
|
||||
case GpioId::HP2300: out << "HP2300"; break;
|
||||
case GpioId::HP2400: out << "HP2400"; break;
|
||||
case GpioId::HP3670: out << "HP3670"; break;
|
||||
case GpioId::HP_N6310: out << "HP_N6310"; break;
|
||||
case GpioId::IMG101: out << "IMG101"; break;
|
||||
case GpioId::KVSS080: out << "KVSS080"; break;
|
||||
case GpioId::MD_5345: out << "MD_5345"; break;
|
||||
case GpioId::PLUSTEK_OPTICBOOK_3800: out << "PLUSTEK_OPTICBOOK_3800"; break;
|
||||
case GpioId::PLUSTEK_OPTICFILM_7200I: out << "PLUSTEK_OPTICFILM_7200I"; break;
|
||||
case GpioId::PLUSTEK_OPTICFILM_7300: out << "PLUSTEK_OPTICFILM_7300"; break;
|
||||
case GpioId::PLUSTEK_OPTICFILM_7400: out << "PLUSTEK_OPTICFILM_7400"; break;
|
||||
case GpioId::PLUSTEK_OPTICFILM_7500I: out << "PLUSTEK_OPTICFILM_7500I"; break;
|
||||
case GpioId::PLUSTEK_OPTICFILM_8200I: out << "PLUSTEK_OPTICFILM_8200I"; break;
|
||||
case GpioId::PLUSTEK_OPTICPRO_3600: out << "PLUSTEK_OPTICPRO_3600"; break;
|
||||
case GpioId::ST12: out << "ST12"; break;
|
||||
case GpioId::ST24: out << "ST24"; break;
|
||||
case GpioId::UMAX: out << "UMAX"; break;
|
||||
case GpioId::XP200: out << "XP200"; break;
|
||||
case GpioId::XP300: out << "XP300"; break;
|
||||
default: out << static_cast<unsigned>(id); break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, MotorId id)
|
||||
{
|
||||
switch (id) {
|
||||
case MotorId::UNKNOWN: out << "UNKNOWN"; break;
|
||||
case MotorId::CANON_LIDE_100: out << "CANON_LIDE_100"; break;
|
||||
case MotorId::CANON_LIDE_110: out << "CANON_LIDE_110"; break;
|
||||
case MotorId::CANON_LIDE_120: out << "CANON_LIDE_120"; break;
|
||||
case MotorId::CANON_LIDE_200: out << "CANON_LIDE_200"; break;
|
||||
case MotorId::CANON_LIDE_210: out << "CANON_LIDE_210"; break;
|
||||
case MotorId::CANON_LIDE_35: out << "CANON_LIDE_35"; break;
|
||||
case MotorId::CANON_LIDE_60: out << "CANON_LIDE_60"; break;
|
||||
case MotorId::CANON_LIDE_700: out << "CANON_LIDE_700"; break;
|
||||
case MotorId::CANON_LIDE_80: out << "CANON_LIDE_80"; break;
|
||||
case MotorId::CANON_4400F: out << "CANON_4400F"; break;
|
||||
case MotorId::CANON_8400F: out << "CANON_8400F"; break;
|
||||
case MotorId::CANON_8600F: out << "CANON_8600F"; break;
|
||||
case MotorId::DP665: out << "DP665"; break;
|
||||
case MotorId::DSMOBILE_600: out << "DSMOBILE_600"; break;
|
||||
case MotorId::G4050: out << "G4050"; break;
|
||||
case MotorId::HP2300: out << "HP2300"; break;
|
||||
case MotorId::HP2400: out << "HP2400"; break;
|
||||
case MotorId::HP3670: out << "HP3670"; break;
|
||||
case MotorId::IMG101: out << "IMG101"; break;
|
||||
case MotorId::KVSS080: out << "KVSS080"; break;
|
||||
case MotorId::MD_5345: out << "MD_5345"; break;
|
||||
case MotorId::PLUSTEK_OPTICBOOK_3800: out << "PLUSTEK_OPTICBOOK_3800"; break;
|
||||
case MotorId::PLUSTEK_OPTICFILM_7200I: out << "PLUSTEK_OPTICFILM_7200I"; break;
|
||||
case MotorId::PLUSTEK_OPTICFILM_7300: out << "PLUSTEK_OPTICFILM_7300"; break;
|
||||
case MotorId::PLUSTEK_OPTICFILM_7400: out << "PLUSTEK_OPTICFILM_7400"; break;
|
||||
case MotorId::PLUSTEK_OPTICFILM_7500I: out << "PLUSTEK_OPTICFILM_7500I"; break;
|
||||
case MotorId::PLUSTEK_OPTICFILM_8200I: out << "PLUSTEK_OPTICFILM_8200I"; break;
|
||||
case MotorId::PLUSTEK_OPTICPRO_3600: out << "PLUSTEK_OPTICPRO_3600"; break;
|
||||
case MotorId::ROADWARRIOR: out << "ROADWARRIOR"; break;
|
||||
case MotorId::ST24: out << "ST24"; break;
|
||||
case MotorId::UMAX: out << "UMAX"; break;
|
||||
case MotorId::XP200: out << "XP200"; break;
|
||||
case MotorId::XP300: out << "XP300"; break;
|
||||
default: out << static_cast<unsigned>(id); break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, StepType type)
|
||||
{
|
||||
switch (type) {
|
||||
|
|
|
@ -201,9 +201,12 @@ enum class ModelId : unsigned
|
|||
PANASONIC_KV_SS080,
|
||||
PENTAX_DSMOBILE_600,
|
||||
PLUSTEK_OPTICBOOK_3800,
|
||||
PLUSTEK_OPTICFILM_7200,
|
||||
PLUSTEK_OPTICFILM_7200I,
|
||||
PLUSTEK_OPTICFILM_7300,
|
||||
PLUSTEK_OPTICFILM_7400,
|
||||
PLUSTEK_OPTICFILM_7500I,
|
||||
PLUSTEK_OPTICFILM_8200I,
|
||||
PLUSTEK_OPTICPRO_3600,
|
||||
PLUSTEK_OPTICPRO_ST12,
|
||||
PLUSTEK_OPTICPRO_ST24,
|
||||
|
@ -222,6 +225,21 @@ enum class ModelId : unsigned
|
|||
XEROX_TRAVELSCANNER_100,
|
||||
};
|
||||
|
||||
inline void serialize(std::istream& str, ModelId& x)
|
||||
{
|
||||
unsigned value;
|
||||
serialize(str, value);
|
||||
x = static_cast<ModelId>(value);
|
||||
}
|
||||
|
||||
inline void serialize(std::ostream& str, ModelId& x)
|
||||
{
|
||||
unsigned value = static_cast<unsigned>(x);
|
||||
serialize(str, value);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, ModelId id);
|
||||
|
||||
enum class SensorId : unsigned
|
||||
{
|
||||
UNKNOWN = 0,
|
||||
|
@ -232,6 +250,7 @@ enum class SensorId : unsigned
|
|||
CCD_DP665,
|
||||
CCD_DP685,
|
||||
CCD_DSMOBILE600,
|
||||
CCD_DOCKETPORT_487,
|
||||
CCD_G4050,
|
||||
CCD_HP2300,
|
||||
CCD_HP2400,
|
||||
|
@ -241,9 +260,12 @@ enum class SensorId : unsigned
|
|||
CCD_IMG101,
|
||||
CCD_KVSS080,
|
||||
CCD_PLUSTEK_OPTICBOOK_3800,
|
||||
CCD_PLUSTEK_OPTICFILM_7200,
|
||||
CCD_PLUSTEK_OPTICFILM_7200I,
|
||||
CCD_PLUSTEK_OPTICFILM_7300,
|
||||
CCD_PLUSTEK_OPTICFILM_7400,
|
||||
CCD_PLUSTEK_OPTICFILM_7500I,
|
||||
CCD_PLUSTEK_OPTICFILM_8200I,
|
||||
CCD_PLUSTEK_OPTICPRO_3600,
|
||||
CCD_ROADWARRIOR,
|
||||
CCD_ST12, // SONY ILX548: 5340 Pixel ???
|
||||
|
@ -251,6 +273,7 @@ enum class SensorId : unsigned
|
|||
CCD_UMAX,
|
||||
CCD_XP300,
|
||||
CIS_CANON_LIDE_35,
|
||||
CIS_CANON_LIDE_60,
|
||||
CIS_CANON_LIDE_80,
|
||||
CIS_CANON_LIDE_100,
|
||||
CIS_CANON_LIDE_110,
|
||||
|
@ -293,9 +316,12 @@ enum class AdcId : unsigned
|
|||
IMG101,
|
||||
KVSS080,
|
||||
PLUSTEK_OPTICBOOK_3800,
|
||||
PLUSTEK_OPTICFILM_7200,
|
||||
PLUSTEK_OPTICFILM_7200I,
|
||||
PLUSTEK_OPTICFILM_7300,
|
||||
PLUSTEK_OPTICFILM_7400,
|
||||
PLUSTEK_OPTICFILM_7500I,
|
||||
PLUSTEK_OPTICFILM_8200I,
|
||||
PLUSTEK_OPTICPRO_3600,
|
||||
WOLFSON_5345,
|
||||
WOLFSON_DSM600,
|
||||
|
@ -321,6 +347,8 @@ inline void serialize(std::ostream& str, AdcId& x)
|
|||
serialize(str, value);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, AdcId id);
|
||||
|
||||
enum class GpioId : unsigned
|
||||
{
|
||||
UNKNOWN = 0,
|
||||
|
@ -345,9 +373,12 @@ enum class GpioId : unsigned
|
|||
KVSS080,
|
||||
MD_5345,
|
||||
PLUSTEK_OPTICBOOK_3800,
|
||||
PLUSTEK_OPTICFILM_7200,
|
||||
PLUSTEK_OPTICFILM_7200I,
|
||||
PLUSTEK_OPTICFILM_7300,
|
||||
PLUSTEK_OPTICFILM_7400,
|
||||
PLUSTEK_OPTICFILM_7500I,
|
||||
PLUSTEK_OPTICFILM_8200I,
|
||||
PLUSTEK_OPTICPRO_3600,
|
||||
ST12,
|
||||
ST24,
|
||||
|
@ -356,6 +387,8 @@ enum class GpioId : unsigned
|
|||
XP300,
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, GpioId id);
|
||||
|
||||
enum class MotorId : unsigned
|
||||
{
|
||||
UNKNOWN = 0,
|
||||
|
@ -365,6 +398,7 @@ enum class MotorId : unsigned
|
|||
CANON_LIDE_200,
|
||||
CANON_LIDE_210,
|
||||
CANON_LIDE_35,
|
||||
CANON_LIDE_60,
|
||||
CANON_LIDE_700,
|
||||
CANON_LIDE_80,
|
||||
CANON_4400F,
|
||||
|
@ -380,9 +414,12 @@ enum class MotorId : unsigned
|
|||
KVSS080,
|
||||
MD_5345,
|
||||
PLUSTEK_OPTICBOOK_3800,
|
||||
PLUSTEK_OPTICFILM_7200,
|
||||
PLUSTEK_OPTICFILM_7200I,
|
||||
PLUSTEK_OPTICFILM_7300,
|
||||
PLUSTEK_OPTICFILM_7400,
|
||||
PLUSTEK_OPTICFILM_7500I,
|
||||
PLUSTEK_OPTICFILM_8200I,
|
||||
PLUSTEK_OPTICPRO_3600,
|
||||
ROADWARRIOR,
|
||||
ST24,
|
||||
|
@ -391,6 +428,8 @@ enum class MotorId : unsigned
|
|||
XP300,
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, MotorId id);
|
||||
|
||||
enum class StepType : unsigned
|
||||
{
|
||||
FULL = 0,
|
||||
|
@ -423,6 +462,7 @@ enum class AsicType : unsigned
|
|||
UNKNOWN = 0,
|
||||
GL646,
|
||||
GL841,
|
||||
GL842,
|
||||
GL843,
|
||||
GL845,
|
||||
GL846,
|
||||
|
@ -431,6 +471,83 @@ enum class AsicType : unsigned
|
|||
};
|
||||
|
||||
|
||||
enum class ModelFlag : unsigned
|
||||
{
|
||||
// no flags
|
||||
NONE = 0,
|
||||
|
||||
// scanner is not tested, print a warning as it's likely it won't work
|
||||
UNTESTED = 1 << 0,
|
||||
|
||||
// use 14-bit gamma table instead of 12-bit
|
||||
GAMMA_14BIT = 1 << 1,
|
||||
|
||||
// perform lamp warmup
|
||||
WARMUP = 1 << 4,
|
||||
|
||||
// whether to disable offset and gain calibration
|
||||
DISABLE_ADC_CALIBRATION = 1 << 5,
|
||||
|
||||
// whether to disable exposure calibration (this currently is only done on CIS
|
||||
// scanners)
|
||||
DISABLE_EXPOSURE_CALIBRATION = 1 << 6,
|
||||
|
||||
// whether to disable shading calibration completely
|
||||
DISABLE_SHADING_CALIBRATION = 1 << 7,
|
||||
|
||||
// do dark calibration
|
||||
DARK_CALIBRATION = 1 << 8,
|
||||
|
||||
// whether scanner must wait for the head while parking
|
||||
MUST_WAIT = 1 << 10,
|
||||
|
||||
// do dark and white calibration in one run
|
||||
DARK_WHITE_CALIBRATION = 1 << 12,
|
||||
|
||||
// allow custom gamma tables
|
||||
CUSTOM_GAMMA = 1 << 13,
|
||||
|
||||
// the scanner uses multi-segment sensors that must be handled during calibration
|
||||
SIS_SENSOR = 1 << 16,
|
||||
|
||||
// the head must be reparked between shading scans
|
||||
SHADING_REPARK = 1 << 18,
|
||||
|
||||
// the scanner outputs inverted pixel data
|
||||
INVERT_PIXEL_DATA = 1 << 19,
|
||||
|
||||
// the scanner outputs 16-bit data that is byte-inverted
|
||||
SWAP_16BIT_DATA = 1 << 20,
|
||||
|
||||
// the scanner has transparency, but it's implemented using only one motor
|
||||
UTA_NO_SECONDARY_MOTOR = 1 << 21,
|
||||
|
||||
// the scanner has transparency, but it's implemented using only one lamp
|
||||
TA_NO_SECONDARY_LAMP = 1 << 22,
|
||||
};
|
||||
|
||||
inline ModelFlag operator|(ModelFlag left, ModelFlag right)
|
||||
{
|
||||
return static_cast<ModelFlag>(static_cast<unsigned>(left) | static_cast<unsigned>(right));
|
||||
}
|
||||
|
||||
inline ModelFlag& operator|=(ModelFlag& left, ModelFlag right)
|
||||
{
|
||||
left = left | right;
|
||||
return left;
|
||||
}
|
||||
|
||||
inline ModelFlag operator&(ModelFlag left, ModelFlag right)
|
||||
{
|
||||
return static_cast<ModelFlag>(static_cast<unsigned>(left) & static_cast<unsigned>(right));
|
||||
}
|
||||
|
||||
inline bool has_flag(ModelFlag flags, ModelFlag which)
|
||||
{
|
||||
return (flags & which) == which;
|
||||
}
|
||||
|
||||
|
||||
enum class ScanFlag : unsigned
|
||||
{
|
||||
NONE = 0,
|
||||
|
@ -438,14 +555,24 @@ enum class ScanFlag : unsigned
|
|||
DISABLE_SHADING = 1 << 1,
|
||||
DISABLE_GAMMA = 1 << 2,
|
||||
DISABLE_BUFFER_FULL_MOVE = 1 << 3,
|
||||
IGNORE_LINE_DISTANCE = 1 << 4,
|
||||
DISABLE_LAMP = 1 << 5,
|
||||
CALIBRATION = 1 << 6,
|
||||
FEEDING = 1 << 7,
|
||||
USE_XPA = 1 << 8,
|
||||
ENABLE_LEDADD = 1 << 9,
|
||||
USE_XCORRECTION = 1 << 10,
|
||||
REVERSE = 1 << 11,
|
||||
|
||||
// if this flag is set the sensor will always be handled ignoring staggering of multiple
|
||||
// sensors to achieve high resolution.
|
||||
IGNORE_STAGGER_OFFSET = 1 << 4,
|
||||
|
||||
// if this flag is set the sensor will always be handled as if the components that scan
|
||||
// different colors are at the same position.
|
||||
IGNORE_COLOR_OFFSET = 1 << 5,
|
||||
|
||||
DISABLE_LAMP = 1 << 6,
|
||||
CALIBRATION = 1 << 7,
|
||||
FEEDING = 1 << 8,
|
||||
USE_XPA = 1 << 9,
|
||||
ENABLE_LEDADD = 1 << 10,
|
||||
REVERSE = 1 << 12,
|
||||
|
||||
// the scanner should return head to home position automatically after scan.
|
||||
AUTO_GO_HOME = 1 << 13,
|
||||
};
|
||||
|
||||
inline ScanFlag operator|(ScanFlag left, ScanFlag right)
|
||||
|
@ -485,45 +612,18 @@ inline void serialize(std::ostream& str, ScanFlag& x)
|
|||
std::ostream& operator<<(std::ostream& out, ScanFlag flags);
|
||||
|
||||
|
||||
|
||||
enum class MotorFlag : unsigned
|
||||
{
|
||||
NONE = 0,
|
||||
AUTO_GO_HOME = 1 << 0,
|
||||
DISABLE_BUFFER_FULL_MOVE = 1 << 2,
|
||||
FEED = 1 << 3,
|
||||
USE_XPA = 1 << 4,
|
||||
REVERSE = 1 << 5,
|
||||
};
|
||||
|
||||
inline MotorFlag operator|(MotorFlag left, MotorFlag right)
|
||||
{
|
||||
return static_cast<MotorFlag>(static_cast<unsigned>(left) | static_cast<unsigned>(right));
|
||||
}
|
||||
|
||||
inline MotorFlag& operator|=(MotorFlag& left, MotorFlag right)
|
||||
{
|
||||
left = left | right;
|
||||
return left;
|
||||
}
|
||||
|
||||
inline MotorFlag operator&(MotorFlag left, MotorFlag right)
|
||||
{
|
||||
return static_cast<MotorFlag>(static_cast<unsigned>(left) & static_cast<unsigned>(right));
|
||||
}
|
||||
|
||||
inline bool has_flag(MotorFlag flags, MotorFlag which)
|
||||
{
|
||||
return (flags & which) == which;
|
||||
}
|
||||
|
||||
|
||||
enum class Direction : unsigned
|
||||
{
|
||||
FORWARD = 0,
|
||||
BACKWARD = 1
|
||||
};
|
||||
|
||||
enum class MotorMode : unsigned
|
||||
{
|
||||
PRIMARY = 0,
|
||||
PRIMARY_AND_SECONDARY,
|
||||
SECONDARY,
|
||||
};
|
||||
|
||||
} // namespace genesys
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
|
||||
#include "error.h"
|
||||
#include <cstdarg>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace genesys {
|
||||
|
||||
|
@ -212,4 +213,32 @@ void DebugMessageHelper::vlog(unsigned level, const char* format, ...)
|
|||
DBG(level, "%s: %s\n", func_, msg.c_str());
|
||||
}
|
||||
|
||||
enum class LogImageDataStatus
|
||||
{
|
||||
NOT_SET,
|
||||
ENABLED,
|
||||
DISABLED
|
||||
};
|
||||
|
||||
static LogImageDataStatus s_log_image_data_setting = LogImageDataStatus::NOT_SET;
|
||||
|
||||
LogImageDataStatus dbg_read_log_image_data_setting()
|
||||
{
|
||||
auto* setting = std::getenv("SANE_DEBUG_GENESYS_IMAGE");
|
||||
if (!setting)
|
||||
return LogImageDataStatus::DISABLED;
|
||||
auto setting_int = std::strtol(setting, nullptr, 10);
|
||||
if (setting_int == 0)
|
||||
return LogImageDataStatus::DISABLED;
|
||||
return LogImageDataStatus::ENABLED;
|
||||
}
|
||||
|
||||
bool dbg_log_image_data()
|
||||
{
|
||||
if (s_log_image_data_setting == LogImageDataStatus::NOT_SET) {
|
||||
s_log_image_data_setting = dbg_read_log_image_data_setting();
|
||||
}
|
||||
return s_log_image_data_setting == LogImageDataStatus::ENABLED;
|
||||
}
|
||||
|
||||
} // namespace genesys
|
||||
|
|
|
@ -137,7 +137,6 @@ private:
|
|||
unsigned num_exceptions_on_enter_ = 0;
|
||||
};
|
||||
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define GENESYS_CURRENT_FUNCTION __PRETTY_FUNCTION__
|
||||
#elif defined(__FUNCSIG__)
|
||||
|
@ -149,6 +148,8 @@ private:
|
|||
#define DBG_HELPER(var) DebugMessageHelper var(GENESYS_CURRENT_FUNCTION)
|
||||
#define DBG_HELPER_ARGS(var, ...) DebugMessageHelper var(GENESYS_CURRENT_FUNCTION, __VA_ARGS__)
|
||||
|
||||
bool dbg_log_image_data();
|
||||
|
||||
template<class F>
|
||||
SANE_Status wrap_exceptions_to_status_code(const char* func, F&& function)
|
||||
{
|
||||
|
|
|
@ -56,7 +56,6 @@ struct Genesys_Calibration_Cache;
|
|||
class CommandSet;
|
||||
|
||||
// device.h
|
||||
class FixedFloat;
|
||||
struct Genesys_Gpo;
|
||||
struct MethodResolutions;
|
||||
struct Genesys_Model;
|
||||
|
@ -75,7 +74,6 @@ class Image;
|
|||
|
||||
// image_buffer.h
|
||||
class ImageBuffer;
|
||||
class FakeBufferModel;
|
||||
class ImageBufferGenesysUsb;
|
||||
|
||||
// image_pipeline.h
|
||||
|
@ -88,12 +86,12 @@ struct Pixel;
|
|||
struct RawPixel;
|
||||
|
||||
// low.h
|
||||
struct Genesys_USB_Device_Entry;
|
||||
struct Motor_Profile;
|
||||
struct UsbDeviceEntry;
|
||||
|
||||
// motor.h
|
||||
struct Genesys_Motor;
|
||||
struct MotorSlope;
|
||||
struct MotorProfile;
|
||||
struct MotorSlopeTable;
|
||||
|
||||
// register.h
|
||||
|
@ -113,7 +111,6 @@ class ScannerInterfaceUsb;
|
|||
class TestScannerInterface;
|
||||
|
||||
// sensor.h
|
||||
class ResolutionFilter;
|
||||
struct GenesysFrontendLayout;
|
||||
struct Genesys_Frontend;
|
||||
struct SensorExposure;
|
||||
|
@ -124,6 +121,10 @@ struct Genesys_Settings;
|
|||
struct SetupParams;
|
||||
struct ScanSession;
|
||||
|
||||
// value_filter.h
|
||||
template<class T> class ValueFilter;
|
||||
template<class T> class ValueFilterAny;
|
||||
|
||||
// test_usb_device.h
|
||||
class TestUsbDevice;
|
||||
|
||||
|
|
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
|
@ -45,74 +45,12 @@
|
|||
#define BACKEND_GENESYS_GL124_H
|
||||
|
||||
#include "genesys.h"
|
||||
#include "command_set.h"
|
||||
#include "command_set_common.h"
|
||||
|
||||
namespace genesys {
|
||||
namespace gl124 {
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t r31;
|
||||
uint8_t r32;
|
||||
uint8_t r33;
|
||||
uint8_t r34;
|
||||
uint8_t r35;
|
||||
uint8_t r36;
|
||||
uint8_t r38;
|
||||
} Gpio_layout;
|
||||
|
||||
/** @brief gpio layout
|
||||
* describes initial gpio settings for a given model
|
||||
* registers 0x31 to 0x38
|
||||
*/
|
||||
static Gpio_layout gpios[]={
|
||||
/* LiDE 110 */
|
||||
{ /* 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38 */
|
||||
0x9f, 0x59, 0x01, 0x80, 0x5f, 0x01, 0x00
|
||||
},
|
||||
/* LiDE 210 */
|
||||
{
|
||||
0x9f, 0x59, 0x01, 0x80, 0x5f, 0x01, 0x00
|
||||
},
|
||||
/* LiDE 120 */
|
||||
{
|
||||
0x9f, 0x53, 0x01, 0x80, 0x5f, 0x01, 0x00
|
||||
},
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t rd0;
|
||||
uint8_t rd1;
|
||||
uint8_t rd2;
|
||||
uint8_t re0;
|
||||
uint8_t re1;
|
||||
uint8_t re2;
|
||||
uint8_t re3;
|
||||
uint8_t re4;
|
||||
uint8_t re5;
|
||||
uint8_t re6;
|
||||
uint8_t re7;
|
||||
} Memory_layout;
|
||||
|
||||
static Memory_layout layouts[]={
|
||||
/* LIDE 110, 120 */
|
||||
{ /* 0xd0 0xd1 0xd2 */
|
||||
0x0a, 0x15, 0x20,
|
||||
/* 0xe0 0xe1 0xe2 0xe3 0xe4 0xe5 0xe6 0xe7 */
|
||||
0x00, 0xac, 0x08, 0x55, 0x08, 0x56, 0x0f, 0xff
|
||||
},
|
||||
/* LIDE 210, 220 */
|
||||
{
|
||||
0x0a, 0x1f, 0x34,
|
||||
0x01, 0x24, 0x08, 0x91, 0x08, 0x92, 0x0f, 0xff
|
||||
}
|
||||
};
|
||||
|
||||
static void gl124_send_slope_table(Genesys_Device* dev, int table_nr,
|
||||
const std::vector<uint16_t>& slope_table, int steps);
|
||||
|
||||
class CommandSetGl124 : public CommandSet
|
||||
class CommandSetGl124 : public CommandSetCommon
|
||||
{
|
||||
public:
|
||||
~CommandSetGl124() override = default;
|
||||
|
@ -122,16 +60,13 @@ public:
|
|||
void init(Genesys_Device* dev) const override;
|
||||
|
||||
void init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* regs, int* channels,
|
||||
int* total_size) const override;
|
||||
|
||||
void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
Genesys_Register_Set* regs) const override;
|
||||
|
||||
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg,
|
||||
|
@ -148,8 +83,6 @@ public:
|
|||
|
||||
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
|
||||
void search_start_position(Genesys_Device* dev) const override;
|
||||
|
||||
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
|
@ -175,9 +108,6 @@ public:
|
|||
|
||||
void eject_document(Genesys_Device* dev) const override;
|
||||
|
||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
bool forward, bool black) const override;
|
||||
|
||||
void move_to_ta(Genesys_Device* dev) const override;
|
||||
|
||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -48,395 +48,13 @@
|
|||
#define BACKEND_GENESYS_GL646_H
|
||||
|
||||
#include "genesys.h"
|
||||
#include "command_set.h"
|
||||
#include "command_set_common.h"
|
||||
#include "motor.h"
|
||||
|
||||
namespace genesys {
|
||||
namespace gl646 {
|
||||
|
||||
static void gl646_set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t set, int dpi);
|
||||
|
||||
/**
|
||||
* sets up the scanner for a scan, registers, gamma tables, shading tables
|
||||
* and slope tables, based on the parameter struct.
|
||||
* @param dev device to set up
|
||||
* @param regs registers to set up
|
||||
* @param settings settings of the scan
|
||||
* @param split true if move before scan has to be done
|
||||
* @param xcorrection true if scanner's X geometry must be taken into account to
|
||||
* compute X, ie add left margins
|
||||
* @param ycorrection true if scanner's Y geometry must be taken into account to
|
||||
* compute Y, ie add top margins
|
||||
*/
|
||||
static void setup_for_scan(Genesys_Device* device,
|
||||
const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set*regs,
|
||||
Genesys_Settings settings,
|
||||
bool split,
|
||||
bool xcorrection,
|
||||
bool ycorrection,
|
||||
bool reverse);
|
||||
|
||||
/**
|
||||
* Does a simple move of the given distance by doing a scan at lowest resolution
|
||||
* shading correction. Memory for data is allocated in this function
|
||||
* and must be freed by caller.
|
||||
* @param dev device of the scanner
|
||||
* @param distance distance to move in MM
|
||||
*/
|
||||
static void simple_move(Genesys_Device* dev, SANE_Int distance);
|
||||
|
||||
/**
|
||||
* Does a simple scan of the area given by the settings. Scanned data
|
||||
* it put in an allocated area which must be freed by the caller.
|
||||
* and slope tables, based on the parameter struct. There is no shading
|
||||
* correction while gamma correction is active.
|
||||
* @param dev device to set up
|
||||
* @param settings settings of the scan
|
||||
* @param move flag to enable scanhead to move
|
||||
* @param forward flag to tell movement direction
|
||||
* @param shading flag to tell if shading correction should be done
|
||||
* @param data pointer that will point to the scanned data
|
||||
*/
|
||||
static void simple_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Settings settings, bool move, bool forward,
|
||||
bool shading, std::vector<uint8_t>& data, const char* test_identifier);
|
||||
|
||||
/**
|
||||
* Send the stop scan command
|
||||
* */
|
||||
static void end_scan_impl(Genesys_Device* dev, Genesys_Register_Set* reg, bool check_stop,
|
||||
bool eject);
|
||||
/**
|
||||
* writes control data to an area behind the last motor table.
|
||||
*/
|
||||
static void write_control(Genesys_Device* dev, const Genesys_Sensor& sensor, int resolution);
|
||||
|
||||
|
||||
/**
|
||||
* initialize scanner's registers at SANE init time
|
||||
*/
|
||||
static void gl646_init_regs (Genesys_Device * dev);
|
||||
|
||||
/**
|
||||
* master motor settings table entry
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/* key */
|
||||
MotorId motor_id;
|
||||
unsigned dpi;
|
||||
unsigned channels;
|
||||
|
||||
/* settings */
|
||||
StepType steptype;
|
||||
bool fastmod; // fast scanning
|
||||
bool fastfed; // fast fed slope tables
|
||||
SANE_Int mtrpwm;
|
||||
MotorSlope slope1;
|
||||
MotorSlope slope2;
|
||||
SANE_Int fwdbwd; /* forward/backward steps */
|
||||
} Motor_Master;
|
||||
|
||||
/**
|
||||
* master motor settings, for a given motor and dpi,
|
||||
* it gives steps and speed informations
|
||||
*/
|
||||
static Motor_Master motor_master[] = {
|
||||
/* HP3670 motor settings */
|
||||
{MotorId::HP3670, 50, 3, StepType::HALF, false, true, 1,
|
||||
MotorSlope::create_from_steps(2329, 120, 229),
|
||||
MotorSlope::create_from_steps(3399, 337, 192), 192},
|
||||
|
||||
{MotorId::HP3670, 75, 3, StepType::FULL, false, true, 1,
|
||||
MotorSlope::create_from_steps(3429, 305, 200),
|
||||
MotorSlope::create_from_steps(3399, 337, 192), 192},
|
||||
|
||||
{MotorId::HP3670, 100, 3, StepType::HALF, false, true, 1,
|
||||
MotorSlope::create_from_steps(2905, 187, 143),
|
||||
MotorSlope::create_from_steps(3399, 337, 192), 192},
|
||||
|
||||
{MotorId::HP3670, 150, 3, StepType::HALF, false, true, 1,
|
||||
MotorSlope::create_from_steps(3429, 305, 73),
|
||||
MotorSlope::create_from_steps(3399, 337, 192), 192},
|
||||
|
||||
{MotorId::HP3670, 300, 3, StepType::HALF, false, true, 1,
|
||||
MotorSlope::create_from_steps(1055, 563, 11),
|
||||
MotorSlope::create_from_steps(3399, 337, 192), 192},
|
||||
|
||||
{MotorId::HP3670, 600, 3, StepType::FULL, false, true, 0,
|
||||
MotorSlope::create_from_steps(10687, 5126, 3),
|
||||
MotorSlope::create_from_steps(3399, 337, 192), 192},
|
||||
|
||||
{MotorId::HP3670,1200, 3, StepType::HALF, false, true, 0,
|
||||
MotorSlope::create_from_steps(15937, 6375, 3),
|
||||
MotorSlope::create_from_steps(3399, 337, 192), 192},
|
||||
|
||||
{MotorId::HP3670, 50, 1, StepType::HALF, false, true, 1,
|
||||
MotorSlope::create_from_steps(2329, 120, 229),
|
||||
MotorSlope::create_from_steps(3399, 337, 192), 192},
|
||||
|
||||
{MotorId::HP3670, 75, 1, StepType::FULL, false, true, 1,
|
||||
MotorSlope::create_from_steps(3429, 305, 200),
|
||||
MotorSlope::create_from_steps(3399, 337, 192), 192},
|
||||
|
||||
{MotorId::HP3670, 100, 1, StepType::HALF, false, true, 1,
|
||||
MotorSlope::create_from_steps(2905, 187, 143),
|
||||
MotorSlope::create_from_steps(3399, 337, 192), 192},
|
||||
|
||||
{MotorId::HP3670, 150, 1, StepType::HALF, false, true, 1,
|
||||
MotorSlope::create_from_steps(3429, 305, 73),
|
||||
MotorSlope::create_from_steps(3399, 337, 192), 192},
|
||||
|
||||
{MotorId::HP3670, 300, 1, StepType::HALF, false, true, 1,
|
||||
MotorSlope::create_from_steps(1055, 563, 11),
|
||||
MotorSlope::create_from_steps(3399, 337, 192), 192},
|
||||
|
||||
{MotorId::HP3670, 600, 1, StepType::FULL, false, true, 0,
|
||||
MotorSlope::create_from_steps(10687, 5126, 3),
|
||||
MotorSlope::create_from_steps(3399, 337, 192), 192},
|
||||
|
||||
{MotorId::HP3670,1200, 1, StepType::HALF, false, true, 0,
|
||||
MotorSlope::create_from_steps(15937, 6375, 3),
|
||||
MotorSlope::create_from_steps(3399, 337, 192), 192},
|
||||
|
||||
/* HP2400/G2410 motor settings base motor dpi = 600 */
|
||||
{MotorId::HP2400, 50, 3, StepType::FULL, false, true, 63,
|
||||
MotorSlope::create_from_steps(8736, 601, 120),
|
||||
MotorSlope::create_from_steps(4905, 337, 192), 192},
|
||||
|
||||
{MotorId::HP2400, 100, 3, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(8736, 601, 120),
|
||||
MotorSlope::create_from_steps(4905, 337, 192), 192},
|
||||
|
||||
{MotorId::HP2400, 150, 3, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(15902, 902, 67),
|
||||
MotorSlope::create_from_steps(4905, 337, 192), 192},
|
||||
|
||||
{MotorId::HP2400, 300, 3, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(16703, 2188, 32),
|
||||
MotorSlope::create_from_steps(4905, 337, 192), 192},
|
||||
|
||||
{MotorId::HP2400, 600, 3, StepType::FULL, false, true, 63,
|
||||
MotorSlope::create_from_steps(18761, 18761, 3),
|
||||
MotorSlope::create_from_steps(4905, 627, 192), 192},
|
||||
|
||||
{MotorId::HP2400,1200, 3, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(43501, 43501, 3),
|
||||
MotorSlope::create_from_steps(4905, 627, 192), 192},
|
||||
|
||||
{MotorId::HP2400, 50, 1, StepType::FULL, false, true, 63,
|
||||
MotorSlope::create_from_steps(8736, 601, 120),
|
||||
MotorSlope::create_from_steps(4905, 337, 192), 192},
|
||||
|
||||
{MotorId::HP2400, 100, 1, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(8736, 601, 120),
|
||||
MotorSlope::create_from_steps(4905, 337, 192), 192},
|
||||
|
||||
{MotorId::HP2400, 150, 1, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(15902, 902, 67),
|
||||
MotorSlope::create_from_steps(4905, 337, 192), 192},
|
||||
|
||||
{MotorId::HP2400, 300, 1, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(16703, 2188, 32),
|
||||
MotorSlope::create_from_steps(4905, 337, 192), 192},
|
||||
|
||||
{MotorId::HP2400, 600, 1, StepType::FULL, false, true, 63,
|
||||
MotorSlope::create_from_steps(18761, 18761, 3),
|
||||
MotorSlope::create_from_steps(4905, 337, 192), 192},
|
||||
|
||||
{MotorId::HP2400,1200, 1, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(43501, 43501, 3),
|
||||
MotorSlope::create_from_steps(4905, 337, 192), 192},
|
||||
|
||||
/* XP 200 motor settings */
|
||||
{MotorId::XP200, 75, 3, StepType::HALF, true, false, 0,
|
||||
MotorSlope::create_from_steps(6000, 2136, 4),
|
||||
MotorSlope::create_from_steps(12000, 1200, 8), 1},
|
||||
|
||||
{MotorId::XP200, 100, 3, StepType::HALF, true, false, 0,
|
||||
MotorSlope::create_from_steps(6000, 2850, 4),
|
||||
MotorSlope::create_from_steps(12000, 1200, 8), 1},
|
||||
|
||||
{MotorId::XP200, 200, 3, StepType::HALF, true, false, 0,
|
||||
MotorSlope::create_from_steps(6999, 5700, 4),
|
||||
MotorSlope::create_from_steps(12000, 1200, 8), 1},
|
||||
|
||||
{MotorId::XP200, 250, 3, StepType::HALF, true, false, 0,
|
||||
MotorSlope::create_from_steps(6999, 6999, 4),
|
||||
MotorSlope::create_from_steps(12000, 1200, 8), 1},
|
||||
|
||||
{MotorId::XP200, 300, 3, StepType::HALF, true, false, 0,
|
||||
MotorSlope::create_from_steps(13500, 13500, 4),
|
||||
MotorSlope::create_from_steps(12000, 1200, 8), 1},
|
||||
|
||||
{MotorId::XP200, 600, 3, StepType::HALF, true, true, 0,
|
||||
MotorSlope::create_from_steps(31998, 31998, 4),
|
||||
MotorSlope::create_from_steps(12000, 1200, 2), 1},
|
||||
|
||||
{MotorId::XP200, 75, 1, StepType::HALF, true, false, 0,
|
||||
MotorSlope::create_from_steps(6000, 2000, 4),
|
||||
MotorSlope::create_from_steps(12000, 1200, 8), 1},
|
||||
|
||||
{MotorId::XP200, 100, 1, StepType::HALF, true, false, 0,
|
||||
MotorSlope::create_from_steps(6000, 1300, 4),
|
||||
MotorSlope::create_from_steps(12000, 1200, 8), 1},
|
||||
|
||||
{MotorId::XP200, 200, 1, StepType::HALF, true, true, 0,
|
||||
MotorSlope::create_from_steps(6000, 3666, 4),
|
||||
MotorSlope::create_from_steps(12000, 1200, 8), 1},
|
||||
|
||||
{MotorId::XP200, 300, 1, StepType::HALF, true, false, 0,
|
||||
MotorSlope::create_from_steps(6500, 6500, 4),
|
||||
MotorSlope::create_from_steps(12000, 1200, 8), 1},
|
||||
|
||||
{MotorId::XP200, 600, 1, StepType::HALF, true, true, 0,
|
||||
MotorSlope::create_from_steps(24000, 24000, 4),
|
||||
MotorSlope::create_from_steps(12000, 1200, 2), 1},
|
||||
|
||||
/* HP scanjet 2300c */
|
||||
{MotorId::HP2300, 75, 3, StepType::FULL, false, true, 63,
|
||||
MotorSlope::create_from_steps(8139, 560, 120),
|
||||
MotorSlope::create_from_steps(4905, 337, 120), 16},
|
||||
|
||||
{MotorId::HP2300, 150, 3, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(7903, 543, 67),
|
||||
MotorSlope::create_from_steps(4905, 337, 120), 16},
|
||||
|
||||
{MotorId::HP2300, 300, 3, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(2175, 1087, 3),
|
||||
MotorSlope::create_from_steps(4905, 337, 120), 16},
|
||||
|
||||
{MotorId::HP2300, 600, 3, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(8700, 4350, 3),
|
||||
MotorSlope::create_from_steps(4905, 337, 120), 16},
|
||||
|
||||
{MotorId::HP2300,1200, 3, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(17400, 8700, 3),
|
||||
MotorSlope::create_from_steps(4905, 337, 120), 16},
|
||||
|
||||
{MotorId::HP2300, 75, 1, StepType::FULL, false, true, 63,
|
||||
MotorSlope::create_from_steps(8139, 560, 120),
|
||||
MotorSlope::create_from_steps(4905, 337, 120), 16},
|
||||
|
||||
{MotorId::HP2300, 150, 1, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(7903, 543, 67),
|
||||
MotorSlope::create_from_steps(4905, 337, 120), 16},
|
||||
|
||||
{MotorId::HP2300, 300, 1, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(2175, 1087, 3),
|
||||
MotorSlope::create_from_steps(4905, 337, 120), 16},
|
||||
|
||||
{MotorId::HP2300, 600, 1, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(8700, 4350, 3),
|
||||
MotorSlope::create_from_steps(4905, 337, 120), 16},
|
||||
|
||||
{MotorId::HP2300,1200, 1, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(17400, 8700, 3),
|
||||
MotorSlope::create_from_steps(4905, 337, 120), 16},
|
||||
|
||||
/* non half ccd settings for 300 dpi
|
||||
{MotorId::HP2300, 300, 3, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(5386, 2175, 44),
|
||||
MotorSlope::create_from_steps(4905, 337, 120), 16},
|
||||
|
||||
{MotorId::HP2300, 300, 1, StepType::HALF, false, true, 63,
|
||||
MotorSlope::create_from_steps(5386, 2175, 44),
|
||||
MotorSlope::create_from_steps(4905, 337, 120), 16},
|
||||
*/
|
||||
|
||||
/* MD5345/6471 motor settings */
|
||||
/* vfinal=(exposure/(1200/dpi))/step_type */
|
||||
{MotorId::MD_5345, 50, 3, StepType::HALF, false, true, 2,
|
||||
MotorSlope::create_from_steps(2500, 250, 255),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 64},
|
||||
|
||||
{MotorId::MD_5345, 75, 3, StepType::HALF, false, true, 2,
|
||||
MotorSlope::create_from_steps(2500, 343, 255),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 64},
|
||||
|
||||
{MotorId::MD_5345, 100, 3, StepType::HALF, false, true, 2,
|
||||
MotorSlope::create_from_steps(2500, 458, 255),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 64},
|
||||
|
||||
{MotorId::MD_5345, 150, 3, StepType::HALF, false, true, 2,
|
||||
MotorSlope::create_from_steps(2500, 687, 255),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 64},
|
||||
|
||||
{MotorId::MD_5345, 200, 3, StepType::HALF, false, true, 2,
|
||||
MotorSlope::create_from_steps(2500, 916, 255),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 64},
|
||||
|
||||
{MotorId::MD_5345, 300, 3, StepType::HALF, false, true, 2,
|
||||
MotorSlope::create_from_steps(2500, 1375, 255),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 64},
|
||||
|
||||
{MotorId::MD_5345, 400, 3, StepType::HALF, false, true, 0,
|
||||
MotorSlope::create_from_steps(2000, 1833, 32),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 32},
|
||||
|
||||
{MotorId::MD_5345, 500, 3, StepType::HALF, false, true, 0,
|
||||
MotorSlope::create_from_steps(2291, 2291, 32),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 32},
|
||||
|
||||
{MotorId::MD_5345, 600, 3, StepType::HALF, false, true, 0,
|
||||
MotorSlope::create_from_steps(2750, 2750, 32),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 32},
|
||||
|
||||
{MotorId::MD_5345, 1200, 3, StepType::QUARTER, false, true, 0,
|
||||
MotorSlope::create_from_steps(2750, 2750, 16),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 146},
|
||||
|
||||
{MotorId::MD_5345, 2400, 3, StepType::QUARTER, false, true, 0,
|
||||
MotorSlope::create_from_steps(5500, 5500, 16),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 146},
|
||||
|
||||
{MotorId::MD_5345, 50, 1, StepType::HALF, false, true, 2,
|
||||
MotorSlope::create_from_steps(2500, 250, 255),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 64},
|
||||
|
||||
{MotorId::MD_5345, 75, 1, StepType::HALF, false, true, 2,
|
||||
MotorSlope::create_from_steps(2500, 343, 255),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 64},
|
||||
|
||||
{MotorId::MD_5345, 100, 1, StepType::HALF, false, true, 2,
|
||||
MotorSlope::create_from_steps(2500, 458, 255),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 64},
|
||||
|
||||
{MotorId::MD_5345, 150, 1, StepType::HALF, false, true, 2,
|
||||
MotorSlope::create_from_steps(2500, 687, 255),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 64},
|
||||
|
||||
{MotorId::MD_5345, 200, 1, StepType::HALF, false, true, 2,
|
||||
MotorSlope::create_from_steps(2500, 916, 255),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 64},
|
||||
|
||||
{MotorId::MD_5345, 300, 1, StepType::HALF, false, true, 2,
|
||||
MotorSlope::create_from_steps(2500, 1375, 255),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 64},
|
||||
|
||||
{MotorId::MD_5345, 400, 1, StepType::HALF, false, true, 0,
|
||||
MotorSlope::create_from_steps(2000, 1833, 32),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 32},
|
||||
|
||||
{MotorId::MD_5345, 500, 1, StepType::HALF, false, true, 0,
|
||||
MotorSlope::create_from_steps(2291, 2291, 32),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 32},
|
||||
|
||||
{MotorId::MD_5345, 600, 1, StepType::HALF, false, true, 0,
|
||||
MotorSlope::create_from_steps(2750, 2750, 32),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 32},
|
||||
|
||||
{MotorId::MD_5345, 1200, 1, StepType::QUARTER, false, true, 0,
|
||||
MotorSlope::create_from_steps(2750, 2750, 16),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 146},
|
||||
|
||||
{MotorId::MD_5345, 2400, 1, StepType::QUARTER, false, true, 0,
|
||||
MotorSlope::create_from_steps(5500, 5500, 16),
|
||||
MotorSlope::create_from_steps(2000, 300, 255), 146}, /* 5500 guessed */
|
||||
};
|
||||
|
||||
class CommandSetGl646 : public CommandSet
|
||||
class CommandSetGl646 : public CommandSetCommon
|
||||
{
|
||||
public:
|
||||
~CommandSetGl646() override = default;
|
||||
|
@ -446,16 +64,13 @@ public:
|
|||
void init(Genesys_Device* dev) const override;
|
||||
|
||||
void init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* regs, int* channels,
|
||||
int* total_size) const override;
|
||||
|
||||
void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
Genesys_Register_Set* regs) const override;
|
||||
|
||||
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg,
|
||||
|
@ -472,8 +87,6 @@ public:
|
|||
|
||||
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
|
||||
void search_start_position(Genesys_Device* dev) const override;
|
||||
|
||||
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
|
@ -495,9 +108,6 @@ public:
|
|||
|
||||
void eject_document(Genesys_Device* dev) const override;
|
||||
|
||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
bool forward, bool black) const override;
|
||||
|
||||
void move_to_ta(Genesys_Device* dev) const override;
|
||||
|
||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||
|
|
|
@ -88,6 +88,7 @@ static constexpr RegMask REG_0x04_ADTYPE = 0x30;
|
|||
static constexpr RegMask REG_0x04_FILTER = 0x0c;
|
||||
static constexpr RegMask REG_0x04_FESET = 0x03;
|
||||
|
||||
static constexpr RegAddr REG_0x05 = 0x05;
|
||||
static constexpr RegMask REG_0x05_DPIHW = 0xc0;
|
||||
static constexpr RegMask REG_0x05_DPIHW_600 = 0x00;
|
||||
static constexpr RegMask REG_0x05_DPIHW_1200 = 0x40;
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -42,7 +42,7 @@
|
|||
*/
|
||||
|
||||
#include "genesys.h"
|
||||
#include "command_set.h"
|
||||
#include "command_set_common.h"
|
||||
|
||||
#ifndef BACKEND_GENESYS_GL841_H
|
||||
#define BACKEND_GENESYS_GL841_H
|
||||
|
@ -50,7 +50,7 @@
|
|||
namespace genesys {
|
||||
namespace gl841 {
|
||||
|
||||
class CommandSetGl841 : public CommandSet
|
||||
class CommandSetGl841 : public CommandSetCommon
|
||||
{
|
||||
public:
|
||||
~CommandSetGl841() override = default;
|
||||
|
@ -60,16 +60,13 @@ public:
|
|||
void init(Genesys_Device* dev) const override;
|
||||
|
||||
void init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* regs, int* channels,
|
||||
int* total_size) const override;
|
||||
|
||||
void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
Genesys_Register_Set* regs) const override;
|
||||
|
||||
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg,
|
||||
|
@ -86,8 +83,6 @@ public:
|
|||
|
||||
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
|
||||
void search_start_position(Genesys_Device* dev) const override;
|
||||
|
||||
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
|
@ -103,15 +98,16 @@ public:
|
|||
|
||||
void update_hardware_sensors(struct Genesys_Scanner* s) const override;
|
||||
|
||||
bool needs_update_home_sensor_gpio() const override { return true; }
|
||||
|
||||
void update_home_sensor_gpio(Genesys_Device& dev) const override;
|
||||
|
||||
void load_document(Genesys_Device* dev) const override;
|
||||
|
||||
void detect_document_end(Genesys_Device* dev) const override;
|
||||
|
||||
void eject_document(Genesys_Device* dev) const override;
|
||||
|
||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
bool forward, bool black) const override;
|
||||
|
||||
void move_to_ta(Genesys_Device* dev) const override;
|
||||
|
||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||
|
|
|
@ -224,10 +224,12 @@ static constexpr RegShift REG_0x5ES_DECSEL = 5;
|
|||
static constexpr RegMask REG_0x5E_STOPTIM = 0x1f;
|
||||
static constexpr RegShift REG_0x5ES_STOPTIM = 0;
|
||||
|
||||
static constexpr RegAddr REG_0x60 = 0x60;
|
||||
static constexpr RegMask REG_0x60_ZIMOD = 0x1f;
|
||||
static constexpr RegMask REG_0x61_Z1MOD = 0xff;
|
||||
static constexpr RegMask REG_0x62_Z1MOD = 0xff;
|
||||
|
||||
static constexpr RegAddr REG_0x63 = 0x63;
|
||||
static constexpr RegMask REG_0x63_Z2MOD = 0x1f;
|
||||
static constexpr RegMask REG_0x64_Z2MOD = 0xff;
|
||||
static constexpr RegMask REG_0x65_Z2MOD = 0xff;
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,131 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2010-2013 Stéphane Voltz <stef.dev@free.fr>
|
||||
|
||||
This file is part of the SANE package.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA.
|
||||
|
||||
As a special exception, the authors of SANE give permission for
|
||||
additional uses of the libraries contained in this release of SANE.
|
||||
|
||||
The exception is that, if you link a SANE library with other files
|
||||
to produce an executable, this does not by itself cause the
|
||||
resulting executable to be covered by the GNU General Public
|
||||
License. Your use of that executable is in no way restricted on
|
||||
account of linking the SANE library code into it.
|
||||
|
||||
This exception does not, however, invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public
|
||||
License.
|
||||
|
||||
If you submit changes to SANE to the maintainers to be included in
|
||||
a subsequent release, you agree by submitting the changes that
|
||||
those changes may be distributed with this exception intact.
|
||||
|
||||
If you write modifications of your own for SANE, it is your choice
|
||||
whether to permit this exception to apply to your modifications.
|
||||
If you do not wish that, delete this exception notice.
|
||||
*/
|
||||
|
||||
#include "genesys.h"
|
||||
#include "command_set_common.h"
|
||||
|
||||
#ifndef BACKEND_GENESYS_GL842_H
|
||||
#define BACKEND_GENESYS_GL842_H
|
||||
|
||||
namespace genesys {
|
||||
namespace gl842 {
|
||||
|
||||
class CommandSetGl842 : public CommandSetCommon
|
||||
{
|
||||
public:
|
||||
~CommandSetGl842() override = default;
|
||||
|
||||
bool needs_home_before_init_regs_for_scan(Genesys_Device* dev) const override;
|
||||
|
||||
void init(Genesys_Device* dev) const override;
|
||||
|
||||
void init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* regs) const override;
|
||||
|
||||
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg,
|
||||
const ScanSession& session) const override;
|
||||
|
||||
void set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t set) const override;
|
||||
void set_powersaving(Genesys_Device* dev, int delay) const override;
|
||||
void save_power(Genesys_Device* dev, bool enable) const override;
|
||||
|
||||
void begin_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* regs, bool start_motor) const override;
|
||||
|
||||
void end_scan(Genesys_Device* dev, Genesys_Register_Set* regs, bool check_stop) const override;
|
||||
|
||||
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
|
||||
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs, int dpi) const override;
|
||||
|
||||
SensorExposure led_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void wait_for_motor_stop(Genesys_Device* dev) const override;
|
||||
|
||||
void move_back_home(Genesys_Device* dev, bool wait_until_home) const override;
|
||||
|
||||
void update_hardware_sensors(struct Genesys_Scanner* s) const override;
|
||||
|
||||
void load_document(Genesys_Device* dev) const override;
|
||||
|
||||
void detect_document_end(Genesys_Device* dev) const override;
|
||||
|
||||
void eject_document(Genesys_Device* dev) const override;
|
||||
|
||||
void move_to_ta(Genesys_Device* dev) const override;
|
||||
|
||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||
int size) const override;
|
||||
|
||||
ScanSession calculate_scan_session(const Genesys_Device* dev,
|
||||
const Genesys_Sensor& sensor,
|
||||
const Genesys_Settings& settings) const override;
|
||||
|
||||
void asic_boot(Genesys_Device* dev, bool cold) const override;
|
||||
};
|
||||
|
||||
enum SlopeTable
|
||||
{
|
||||
SCAN_TABLE = 0, // table 1 at 0x4000
|
||||
BACKTRACK_TABLE = 1, // table 2 at 0x4800
|
||||
STOP_TABLE = 2, // table 3 at 0x5000
|
||||
FAST_TABLE = 3, // table 4 at 0x5800
|
||||
HOME_TABLE = 4, // table 5 at 0x6000
|
||||
};
|
||||
|
||||
} // namespace gl842
|
||||
} // namespace genesys
|
||||
|
||||
#endif // BACKEND_GENESYS_GL842_H
|
|
@ -0,0 +1,285 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
|
||||
|
||||
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 BACKEND_GENESYS_gl842_REGISTERS_H
|
||||
#define BACKEND_GENESYS_gl842_REGISTERS_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace genesys {
|
||||
namespace gl842 {
|
||||
|
||||
using RegAddr = std::uint16_t;
|
||||
using RegMask = std::uint8_t;
|
||||
using RegShift = unsigned;
|
||||
|
||||
static constexpr RegAddr REG_0x01 = 0x01;
|
||||
static constexpr RegMask REG_0x01_CISSET = 0x80;
|
||||
static constexpr RegMask REG_0x01_DOGENB = 0x40;
|
||||
static constexpr RegMask REG_0x01_DVDSET = 0x20;
|
||||
static constexpr RegMask REG_0x01_M15DRAM = 0x08;
|
||||
static constexpr RegMask REG_0x01_DRAMSEL = 0x04;
|
||||
static constexpr RegMask REG_0x01_SHDAREA = 0x02;
|
||||
static constexpr RegMask REG_0x01_SCAN = 0x01;
|
||||
|
||||
static constexpr RegAddr REG_0x02 = 0x02;
|
||||
static constexpr RegMask REG_0x02_NOTHOME = 0x80;
|
||||
static constexpr RegMask REG_0x02_ACDCDIS = 0x40;
|
||||
static constexpr RegMask REG_0x02_AGOHOME = 0x20;
|
||||
static constexpr RegMask REG_0x02_MTRPWR = 0x10;
|
||||
static constexpr RegMask REG_0x02_FASTFED = 0x08;
|
||||
static constexpr RegMask REG_0x02_MTRREV = 0x04;
|
||||
static constexpr RegMask REG_0x02_HOMENEG = 0x02;
|
||||
static constexpr RegMask REG_0x02_LONGCURV = 0x01;
|
||||
|
||||
static constexpr RegAddr REG_0x03 = 0x03;
|
||||
static constexpr RegMask REG_0x03_LAMPDOG = 0x80;
|
||||
static constexpr RegMask REG_0x03_AVEENB = 0x40;
|
||||
static constexpr RegMask REG_0x03_XPASEL = 0x20;
|
||||
static constexpr RegMask REG_0x03_LAMPPWR = 0x10;
|
||||
static constexpr RegMask REG_0x03_LAMPTIM = 0x0f;
|
||||
|
||||
static constexpr RegAddr REG_0x04 = 0x04;
|
||||
static constexpr RegMask REG_0x04_LINEART = 0x80;
|
||||
static constexpr RegMask REG_0x04_BITSET = 0x40;
|
||||
static constexpr RegMask REG_0x04_AFEMOD = 0x30;
|
||||
static constexpr RegMask REG_0x04_FILTER = 0x0c;
|
||||
static constexpr RegMask REG_0x04_FESET = 0x03;
|
||||
|
||||
static constexpr RegShift REG_0x04S_AFEMOD = 4;
|
||||
|
||||
static constexpr RegAddr REG_0x05 = 0x05;
|
||||
static constexpr RegMask REG_0x05_DPIHW = 0xc0;
|
||||
static constexpr RegMask REG_0x05_DPIHW_600 = 0x00;
|
||||
static constexpr RegMask REG_0x05_DPIHW_1200 = 0x40;
|
||||
static constexpr RegMask REG_0x05_DPIHW_2400 = 0x80;
|
||||
static constexpr RegMask REG_0x05_DPIHW_4800 = 0xc0;
|
||||
static constexpr RegMask REG_0x05_MTLLAMP = 0x30;
|
||||
static constexpr RegMask REG_0x05_GMMENB = 0x08;
|
||||
static constexpr RegMask REG_0x05_MTLBASE = 0x03;
|
||||
|
||||
static constexpr RegAddr REG_0x06 = 0x06;
|
||||
static constexpr RegMask REG_0x06_SCANMOD = 0xe0;
|
||||
static constexpr RegShift REG_0x06S_SCANMOD = 5;
|
||||
static constexpr RegMask REG_0x06_PWRBIT = 0x10;
|
||||
static constexpr RegMask REG_0x06_GAIN4 = 0x08;
|
||||
static constexpr RegMask REG_0x06_OPTEST = 0x07;
|
||||
|
||||
static constexpr RegMask REG_0x08_DECFLAG = 0x40;
|
||||
static constexpr RegMask REG_0x08_GMMFFR = 0x20;
|
||||
static constexpr RegMask REG_0x08_GMMFFG = 0x10;
|
||||
static constexpr RegMask REG_0x08_GMMFFB = 0x08;
|
||||
static constexpr RegMask REG_0x08_GMMZR = 0x04;
|
||||
static constexpr RegMask REG_0x08_GMMZG = 0x02;
|
||||
static constexpr RegMask REG_0x08_GMMZB = 0x01;
|
||||
|
||||
static constexpr RegMask REG_0x09_MCNTSET = 0xc0;
|
||||
static constexpr RegMask REG_0x09_CLKSET = 0x30;
|
||||
static constexpr RegMask REG_0x09_BACKSCAN = 0x08;
|
||||
static constexpr RegMask REG_0x09_ENHANCE = 0x04;
|
||||
static constexpr RegMask REG_0x09_SHORTTG = 0x02;
|
||||
static constexpr RegMask REG_0x09_NWAIT = 0x01;
|
||||
|
||||
static constexpr RegAddr REG_0x0D = 0x0d;
|
||||
static constexpr RegMask REG_0x0D_CLRLNCNT = 0x01;
|
||||
|
||||
static constexpr RegAddr REG_0x0F = 0x0f;
|
||||
|
||||
static constexpr RegAddr REG_EXPR = 0x10;
|
||||
static constexpr RegAddr REG_EXPG = 0x12;
|
||||
static constexpr RegAddr REG_EXPB = 0x14;
|
||||
|
||||
static constexpr RegMask REG_0x16_CTRLHI = 0x80;
|
||||
static constexpr RegMask REG_0x16_TOSHIBA = 0x40;
|
||||
static constexpr RegMask REG_0x16_TGINV = 0x20;
|
||||
static constexpr RegMask REG_0x16_CK1INV = 0x10;
|
||||
static constexpr RegMask REG_0x16_CK2INV = 0x08;
|
||||
static constexpr RegMask REG_0x16_CTRLINV = 0x04;
|
||||
static constexpr RegMask REG_0x16_CKDIS = 0x02;
|
||||
static constexpr RegMask REG_0x16_CTRLDIS = 0x01;
|
||||
|
||||
static constexpr RegMask REG_0x17_TGMODE = 0xc0;
|
||||
static constexpr RegMask REG_0x17_TGMODE_NO_DUMMY = 0x00;
|
||||
static constexpr RegMask REG_0x17_TGMODE_REF = 0x40;
|
||||
static constexpr RegMask REG_0x17_TGMODE_XPA = 0x80;
|
||||
static constexpr RegMask REG_0x17_TGW = 0x3f;
|
||||
|
||||
static constexpr RegAddr REG_0x18 = 0x18;
|
||||
static constexpr RegMask REG_0x18_CNSET = 0x80;
|
||||
static constexpr RegMask REG_0x18_DCKSEL = 0x60;
|
||||
static constexpr RegMask REG_0x18_CKTOGGLE = 0x10;
|
||||
static constexpr RegMask REG_0x18_CKDELAY = 0x0c;
|
||||
static constexpr RegMask REG_0x18_CKSEL = 0x03;
|
||||
|
||||
static constexpr RegAddr REG_EXPDMY = 0x19;
|
||||
|
||||
static constexpr RegAddr REG_0x1A = 0x1a;
|
||||
static constexpr RegMask REG_0x1A_MANUAL3 = 0x02;
|
||||
static constexpr RegMask REG_0x1A_MANUAL1 = 0x01;
|
||||
static constexpr RegMask REG_0x1A_CK4INV = 0x08;
|
||||
static constexpr RegMask REG_0x1A_CK3INV = 0x04;
|
||||
static constexpr RegMask REG_0x1A_LINECLP = 0x02;
|
||||
|
||||
static constexpr RegAddr REG_0x1C = 0x1c;
|
||||
static constexpr RegMask REG_0x1C_TGTIME = 0x07;
|
||||
|
||||
static constexpr RegMask REG_0x1D_CK4LOW = 0x80;
|
||||
static constexpr RegMask REG_0x1D_CK3LOW = 0x40;
|
||||
static constexpr RegMask REG_0x1D_CK1LOW = 0x20;
|
||||
static constexpr RegMask REG_0x1D_TGSHLD = 0x1f;
|
||||
|
||||
static constexpr RegAddr REG_0x1E = 0x1e;
|
||||
static constexpr RegMask REG_0x1E_WDTIME = 0xf0;
|
||||
static constexpr RegShift REG_0x1ES_WDTIME = 4;
|
||||
static constexpr RegMask REG_0x1E_LINESEL = 0x0f;
|
||||
static constexpr RegShift REG_0x1ES_LINESEL = 0;
|
||||
|
||||
static constexpr RegAddr REG_0x21 = 0x21;
|
||||
static constexpr RegAddr REG_STEPNO = 0x21;
|
||||
static constexpr RegAddr REG_FWDSTEP = 0x22;
|
||||
static constexpr RegAddr REG_BWDSTEP = 0x23;
|
||||
static constexpr RegAddr REG_FASTNO = 0x24;
|
||||
static constexpr RegAddr REG_LINCNT = 0x25;
|
||||
|
||||
static constexpr RegAddr REG_0x29 = 0x29;
|
||||
static constexpr RegAddr REG_0x2A = 0x2a;
|
||||
static constexpr RegAddr REG_0x2B = 0x2b;
|
||||
static constexpr RegAddr REG_DPISET = 0x2c;
|
||||
static constexpr RegAddr REG_0x2E = 0x2e;
|
||||
static constexpr RegAddr REG_0x2F = 0x2f;
|
||||
|
||||
static constexpr RegAddr REG_STRPIXEL = 0x30;
|
||||
static constexpr RegAddr REG_ENDPIXEL = 0x32;
|
||||
static constexpr RegAddr REG_DUMMY = 0x34;
|
||||
static constexpr RegAddr REG_MAXWD = 0x35;
|
||||
static constexpr RegAddr REG_LPERIOD = 0x38;
|
||||
static constexpr RegAddr REG_FEEDL = 0x3d;
|
||||
|
||||
static constexpr RegAddr REG_0x40 = 0x40;
|
||||
static constexpr RegMask REG_0x40_HISPDFLG = 0x04;
|
||||
static constexpr RegMask REG_0x40_MOTMFLG = 0x02;
|
||||
static constexpr RegMask REG_0x40_DATAENB = 0x01;
|
||||
|
||||
static constexpr RegMask REG_0x41_PWRBIT = 0x80;
|
||||
static constexpr RegMask REG_0x41_BUFEMPTY = 0x40;
|
||||
static constexpr RegMask REG_0x41_FEEDFSH = 0x20;
|
||||
static constexpr RegMask REG_0x41_SCANFSH = 0x10;
|
||||
static constexpr RegMask REG_0x41_HOMESNR = 0x08;
|
||||
static constexpr RegMask REG_0x41_LAMPSTS = 0x04;
|
||||
static constexpr RegMask REG_0x41_FEBUSY = 0x02;
|
||||
static constexpr RegMask REG_0x41_MOTORENB = 0x01;
|
||||
|
||||
static constexpr RegMask REG_0x5A_ADCLKINV = 0x80;
|
||||
static constexpr RegMask REG_0x5A_RLCSEL = 0x40;
|
||||
static constexpr RegMask REG_0x5A_CDSREF = 0x30;
|
||||
static constexpr RegShift REG_0x5AS_CDSREF = 4;
|
||||
static constexpr RegMask REG_0x5A_RLC = 0x0f;
|
||||
static constexpr RegShift REG_0x5AS_RLC = 0;
|
||||
|
||||
static constexpr RegAddr REG_0x5E = 0x5e;
|
||||
static constexpr RegMask REG_0x5E_DECSEL = 0xe0;
|
||||
static constexpr RegShift REG_0x5ES_DECSEL = 5;
|
||||
static constexpr RegMask REG_0x5E_STOPTIM = 0x1f;
|
||||
static constexpr RegShift REG_0x5ES_STOPTIM = 0;
|
||||
|
||||
static constexpr RegAddr REG_FMOVDEC = 0x5f;
|
||||
|
||||
static constexpr RegAddr REG_0x60 = 0x60;
|
||||
static constexpr RegMask REG_0x60_Z1MOD = 0x1f;
|
||||
static constexpr RegAddr REG_0x61 = 0x61;
|
||||
static constexpr RegMask REG_0x61_Z1MOD = 0xff;
|
||||
static constexpr RegAddr REG_0x62 = 0x62;
|
||||
static constexpr RegMask REG_0x62_Z1MOD = 0xff;
|
||||
|
||||
static constexpr RegAddr REG_0x63 = 0x63;
|
||||
static constexpr RegMask REG_0x63_Z2MOD = 0x1f;
|
||||
static constexpr RegAddr REG_0x64 = 0x64;
|
||||
static constexpr RegMask REG_0x64_Z2MOD = 0xff;
|
||||
static constexpr RegAddr REG_0x65 = 0x65;
|
||||
static constexpr RegMask REG_0x65_Z2MOD = 0xff;
|
||||
|
||||
static constexpr RegAddr REG_0x67 = 0x67;
|
||||
static constexpr RegAddr REG_0x68 = 0x68;
|
||||
|
||||
static constexpr RegShift REG_0x67S_STEPSEL = 6;
|
||||
static constexpr RegMask REG_0x67_STEPSEL = 0xc0;
|
||||
|
||||
static constexpr RegShift REG_0x68S_FSTPSEL = 6;
|
||||
static constexpr RegMask REG_0x68_FSTPSEL = 0xc0;
|
||||
|
||||
static constexpr RegAddr REG_FSHDEC = 0x69;
|
||||
static constexpr RegAddr REG_FMOVNO = 0x6a;
|
||||
|
||||
static constexpr RegAddr REG_0x6B = 0x6b;
|
||||
static constexpr RegMask REG_0x6B_MULTFILM = 0x80;
|
||||
|
||||
static constexpr RegAddr REG_Z1MOD = 0x60;
|
||||
static constexpr RegAddr REG_Z2MOD = 0x63;
|
||||
|
||||
static constexpr RegAddr REG_0x6C = 0x6c;
|
||||
static constexpr RegAddr REG_0x6D = 0x6d;
|
||||
static constexpr RegAddr REG_0x6E = 0x6e;
|
||||
static constexpr RegAddr REG_0x6F = 0x6f;
|
||||
|
||||
static constexpr RegAddr REG_CK1MAP = 0x74;
|
||||
static constexpr RegAddr REG_CK3MAP = 0x77;
|
||||
static constexpr RegAddr REG_CK4MAP = 0x7a;
|
||||
|
||||
static constexpr RegAddr REG_0x7E = 0x7e;
|
||||
|
||||
static constexpr RegAddr REG_0x80 = 0x80;
|
||||
static constexpr RegMask REG_0x80_TABLE1_NORMAL = 0x03;
|
||||
static constexpr RegShift REG_0x80S_TABLE1_NORMAL = 0;
|
||||
static constexpr RegMask REG_0x80_TABLE2_BACK = 0x0c;
|
||||
static constexpr RegShift REG_0x80S_TABLE2_BACK = 2;
|
||||
static constexpr RegMask REG_0x80_TABLE4_FAST = 0x30;
|
||||
static constexpr RegShift REG_0x80S_TABLE4_FAST = 4;
|
||||
static constexpr RegMask REG_0x80_TABLE5_GO_HOME = 0xc0;
|
||||
static constexpr RegShift REG_0x80S_TABLE5_GO_HOME = 6;
|
||||
|
||||
static constexpr RegMask REG_0x87_LEDADD = 0x04;
|
||||
|
||||
} // namespace gl842
|
||||
} // namespace genesys
|
||||
|
||||
#endif // BACKEND_GENESYS_gl842_REGISTERS_H
|
Plik diff jest za duży
Load Diff
|
@ -42,7 +42,7 @@
|
|||
*/
|
||||
|
||||
#include "genesys.h"
|
||||
#include "command_set.h"
|
||||
#include "command_set_common.h"
|
||||
|
||||
#ifndef BACKEND_GENESYS_GL843_H
|
||||
#define BACKEND_GENESYS_GL843_H
|
||||
|
@ -50,7 +50,7 @@
|
|||
namespace genesys {
|
||||
namespace gl843 {
|
||||
|
||||
class CommandSetGl843 : public CommandSet
|
||||
class CommandSetGl843 : public CommandSetCommon
|
||||
{
|
||||
public:
|
||||
~CommandSetGl843() override = default;
|
||||
|
@ -60,16 +60,13 @@ public:
|
|||
void init(Genesys_Device* dev) const override;
|
||||
|
||||
void init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* regs, int* channels,
|
||||
int* total_size) const override;
|
||||
|
||||
void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
Genesys_Register_Set* regs) const override;
|
||||
|
||||
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg,
|
||||
|
@ -86,8 +83,6 @@ public:
|
|||
|
||||
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
|
||||
void search_start_position(Genesys_Device* dev) const override;
|
||||
|
||||
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
|
@ -109,9 +104,6 @@ public:
|
|||
|
||||
void eject_document(Genesys_Device* dev) const override;
|
||||
|
||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
bool forward, bool black) const override;
|
||||
|
||||
void move_to_ta(Genesys_Device* dev) const override;
|
||||
|
||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||
|
|
|
@ -338,6 +338,16 @@ static constexpr RegAddr REG_CK4MAP = 0x7a;
|
|||
|
||||
static constexpr RegAddr REG_0x7E = 0x7e;
|
||||
|
||||
static constexpr RegAddr REG_0x80 = 0x80;
|
||||
static constexpr RegMask REG_0x80_TABLE1_NORMAL = 0x03;
|
||||
static constexpr RegShift REG_0x80S_TABLE1_NORMAL = 0;
|
||||
static constexpr RegMask REG_0x80_TABLE2_BACK = 0x0c;
|
||||
static constexpr RegShift REG_0x80S_TABLE2_BACK = 2;
|
||||
static constexpr RegMask REG_0x80_TABLE4_FAST = 0x30;
|
||||
static constexpr RegShift REG_0x80S_TABLE4_FAST = 4;
|
||||
static constexpr RegMask REG_0x80_TABLE5_GO_HOME = 0xc0;
|
||||
static constexpr RegShift REG_0x80S_TABLE5_GO_HOME = 6;
|
||||
|
||||
static constexpr RegAddr REG_0x9D = 0x9d;
|
||||
static constexpr RegShift REG_0x9DS_STEPTIM = 2;
|
||||
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -42,7 +42,7 @@
|
|||
*/
|
||||
|
||||
#include "genesys.h"
|
||||
#include "command_set.h"
|
||||
#include "command_set_common.h"
|
||||
|
||||
#ifndef BACKEND_GENESYS_GL846_H
|
||||
#define BACKEND_GENESYS_GL846_H
|
||||
|
@ -50,82 +50,7 @@
|
|||
namespace genesys {
|
||||
namespace gl846 {
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GpioId gpio_id;
|
||||
uint8_t r6b;
|
||||
uint8_t r6c;
|
||||
uint8_t r6d;
|
||||
uint8_t r6e;
|
||||
uint8_t r6f;
|
||||
uint8_t ra6;
|
||||
uint8_t ra7;
|
||||
uint8_t ra8;
|
||||
uint8_t ra9;
|
||||
} Gpio_Profile;
|
||||
|
||||
static Gpio_Profile gpios[]={
|
||||
{ GpioId::IMG101, 0x72, 0x1f, 0xa4, 0x13, 0xa7, 0x11, 0xff, 0x19, 0x05},
|
||||
{ GpioId::PLUSTEK_OPTICBOOK_3800, 0x30, 0x01, 0x80, 0x2d, 0x80, 0x0c, 0x8f, 0x08, 0x04},
|
||||
{ GpioId::UNKNOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *model;
|
||||
uint8_t dramsel;
|
||||
/* shading data address */
|
||||
uint8_t rd0;
|
||||
uint8_t rd1;
|
||||
uint8_t rd2;
|
||||
/* scanned data address */
|
||||
uint8_t rx[24];
|
||||
} Memory_layout;
|
||||
|
||||
static Memory_layout layouts[]={
|
||||
/* Image formula 101 */
|
||||
{
|
||||
"canon-image-formula-101",
|
||||
0x8b,
|
||||
0x0a, 0x1b, 0x00,
|
||||
{ /* RED ODD START / RED ODD END */
|
||||
0x00, 0xb0, 0x05, 0xe7, /* [0x00b0, 0x05e7] 1336*4000w */
|
||||
/* RED EVEN START / RED EVEN END */
|
||||
0x05, 0xe8, 0x0b, 0x1f, /* [0x05e8, 0x0b1f] */
|
||||
/* GREEN ODD START / GREEN ODD END */
|
||||
0x0b, 0x20, 0x10, 0x57, /* [0x0b20, 0x1057] */
|
||||
/* GREEN EVEN START / GREEN EVEN END */
|
||||
0x10, 0x58, 0x15, 0x8f, /* [0x1058, 0x158f] */
|
||||
/* BLUE ODD START / BLUE ODD END */
|
||||
0x15, 0x90, 0x1a, 0xc7, /* [0x1590,0x1ac7] */
|
||||
/* BLUE EVEN START / BLUE EVEN END */
|
||||
0x1a, 0xc8, 0x1f, 0xff /* [0x1ac8,0x1fff] */
|
||||
}
|
||||
},
|
||||
/* OpticBook 3800 */
|
||||
{
|
||||
"plustek-opticbook-3800",
|
||||
0x2a,
|
||||
0x0a, 0x0a, 0x0a,
|
||||
{ /* RED ODD START / RED ODD END */
|
||||
0x00, 0x68, 0x03, 0x00,
|
||||
/* RED EVEN START / RED EVEN END */
|
||||
0x03, 0x01, 0x05, 0x99,
|
||||
/* GREEN ODD START / GREEN ODD END */
|
||||
0x05, 0x9a, 0x08, 0x32,
|
||||
/* GREEN EVEN START / GREEN EVEN END */
|
||||
0x08, 0x33, 0x0a, 0xcb,
|
||||
/* BLUE ODD START / BLUE ODD END */
|
||||
0x0a, 0xcc, 0x0d, 0x64,
|
||||
/* BLUE EVEN START / BLUE EVEN END */
|
||||
0x0d, 0x65, 0x0f, 0xfd
|
||||
}
|
||||
},
|
||||
/* list terminating entry */
|
||||
{ nullptr, 0, 0, 0, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }
|
||||
};
|
||||
|
||||
class CommandSetGl846 : public CommandSet
|
||||
class CommandSetGl846 : public CommandSetCommon
|
||||
{
|
||||
public:
|
||||
~CommandSetGl846() override = default;
|
||||
|
@ -135,16 +60,13 @@ public:
|
|||
void init(Genesys_Device* dev) const override;
|
||||
|
||||
void init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* regs, int* channels,
|
||||
int* total_size) const override;
|
||||
|
||||
void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
Genesys_Register_Set* regs) const override;
|
||||
|
||||
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg,
|
||||
|
@ -161,8 +83,6 @@ public:
|
|||
|
||||
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
|
||||
void search_start_position(Genesys_Device* dev) const override;
|
||||
|
||||
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
|
@ -188,9 +108,6 @@ public:
|
|||
|
||||
void eject_document(Genesys_Device* dev) const override;
|
||||
|
||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
bool forward, bool black) const override;
|
||||
|
||||
void move_to_ta(Genesys_Device* dev) const override;
|
||||
|
||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||
|
|
|
@ -194,7 +194,7 @@ static constexpr RegMask REG_0x1D_CK1LOW = 0x20;
|
|||
static constexpr RegMask REG_0x1D_TGSHLD = 0x1f;
|
||||
static constexpr RegShift REG_0x1DS_TGSHLD = 0;
|
||||
|
||||
|
||||
static constexpr RegAddr REG_0x1E = 0x1e;
|
||||
static constexpr RegMask REG_0x1E_WDTIME = 0xf0;
|
||||
static constexpr RegShift REG_0x1ES_WDTIME = 4;
|
||||
static constexpr RegMask REG_0x1E_LINESEL = 0x0f;
|
||||
|
@ -303,6 +303,16 @@ static constexpr RegAddr REG_0x6E = 0x6e;
|
|||
static constexpr RegAddr REG_0x6F = 0x6f;
|
||||
static constexpr RegAddr REG_0x7E = 0x7e;
|
||||
|
||||
static constexpr RegAddr REG_0x80 = 0x80;
|
||||
static constexpr RegMask REG_0x80_TABLE1_NORMAL = 0x03;
|
||||
static constexpr RegShift REG_0x80S_TABLE1_NORMAL = 0;
|
||||
static constexpr RegMask REG_0x80_TABLE2_BACK = 0x0c;
|
||||
static constexpr RegShift REG_0x80S_TABLE2_BACK = 2;
|
||||
static constexpr RegMask REG_0x80_TABLE4_FAST = 0x30;
|
||||
static constexpr RegShift REG_0x80S_TABLE4_FAST = 4;
|
||||
static constexpr RegMask REG_0x80_TABLE5_GO_HOME = 0xc0;
|
||||
static constexpr RegShift REG_0x80S_TABLE5_GO_HOME = 6;
|
||||
|
||||
static constexpr RegMask REG_0x87_ACYCNRLC = 0x10;
|
||||
static constexpr RegMask REG_0x87_ENOFFSET = 0x08;
|
||||
static constexpr RegMask REG_0x87_LEDADD = 0x04;
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -45,75 +45,12 @@
|
|||
#define BACKEND_GENESYS_GL847_H
|
||||
|
||||
#include "genesys.h"
|
||||
#include "command_set.h"
|
||||
#include "command_set_common.h"
|
||||
|
||||
namespace genesys {
|
||||
namespace gl847 {
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GpioId gpio_id;
|
||||
uint8_t r6b;
|
||||
uint8_t r6c;
|
||||
uint8_t r6d;
|
||||
uint8_t r6e;
|
||||
uint8_t r6f;
|
||||
uint8_t ra6;
|
||||
uint8_t ra7;
|
||||
uint8_t ra8;
|
||||
uint8_t ra9;
|
||||
} Gpio_Profile;
|
||||
|
||||
static Gpio_Profile gpios[]={
|
||||
{ GpioId::CANON_LIDE_200, 0x02, 0xf9, 0x20, 0xff, 0x00, 0x04, 0x04, 0x00, 0x00},
|
||||
{ GpioId::CANON_LIDE_700F, 0x06, 0xdb, 0xff, 0xff, 0x80, 0x15, 0x07, 0x20, 0x10},
|
||||
{ GpioId::UNKNOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t dramsel;
|
||||
uint8_t rd0;
|
||||
uint8_t rd1;
|
||||
uint8_t rd2;
|
||||
uint8_t re0;
|
||||
uint8_t re1;
|
||||
uint8_t re2;
|
||||
uint8_t re3;
|
||||
uint8_t re4;
|
||||
uint8_t re5;
|
||||
uint8_t re6;
|
||||
uint8_t re7;
|
||||
} Memory_layout;
|
||||
|
||||
static Memory_layout layouts[]={
|
||||
/* LIDE 100 */
|
||||
{
|
||||
0x29,
|
||||
0x0a, 0x15, 0x20,
|
||||
0x00, 0xac, 0x02, 0x55, 0x02, 0x56, 0x03, 0xff
|
||||
},
|
||||
/* LIDE 200 */
|
||||
{
|
||||
0x29,
|
||||
0x0a, 0x1f, 0x34,
|
||||
0x01, 0x24, 0x02, 0x91, 0x02, 0x92, 0x03, 0xff
|
||||
},
|
||||
/* 5600F */
|
||||
{
|
||||
0x29,
|
||||
0x0a, 0x1f, 0x34,
|
||||
0x01, 0x24, 0x02, 0x91, 0x02, 0x92, 0x03, 0xff
|
||||
},
|
||||
/* LIDE 700F */
|
||||
{
|
||||
0x2a,
|
||||
0x0a, 0x33, 0x5c,
|
||||
0x02, 0x14, 0x09, 0x09, 0x09, 0x0a, 0x0f, 0xff
|
||||
}
|
||||
};
|
||||
|
||||
class CommandSetGl847 : public CommandSet
|
||||
class CommandSetGl847 : public CommandSetCommon
|
||||
{
|
||||
public:
|
||||
~CommandSetGl847() override = default;
|
||||
|
@ -123,16 +60,13 @@ public:
|
|||
void init(Genesys_Device* dev) const override;
|
||||
|
||||
void init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* regs, int* channels,
|
||||
int* total_size) const override;
|
||||
|
||||
void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
Genesys_Register_Set* regs) const override;
|
||||
|
||||
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg,
|
||||
|
@ -149,8 +83,6 @@ public:
|
|||
|
||||
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
|
||||
void search_start_position(Genesys_Device* dev) const override;
|
||||
|
||||
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
|
@ -176,9 +108,6 @@ public:
|
|||
|
||||
void eject_document(Genesys_Device* dev) const override;
|
||||
|
||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
bool forward, bool black) const override;
|
||||
|
||||
void move_to_ta(Genesys_Device* dev) const override;
|
||||
|
||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||
|
|
|
@ -190,6 +190,7 @@ static constexpr RegMask REG_0x1D_CK1LOW = 0x20;
|
|||
static constexpr RegMask REG_0x1D_TGSHLD = 0x1f;
|
||||
static constexpr RegMask REG_0x1DS_TGSHLD = 0;
|
||||
|
||||
static constexpr RegAddr REG_0x1E = 0x1e;
|
||||
static constexpr RegMask REG_0x1E_WDTIME = 0xf0;
|
||||
static constexpr RegMask REG_0x1ES_WDTIME = 4;
|
||||
static constexpr RegMask REG_0x1E_LINESEL = 0x0f;
|
||||
|
|
|
@ -89,47 +89,11 @@ bool ImageBuffer::get_data(std::size_t size, std::uint8_t* out_data)
|
|||
return got_data;
|
||||
}
|
||||
|
||||
void FakeBufferModel::push_step(std::size_t buffer_size, std::size_t row_bytes)
|
||||
{
|
||||
sizes_.push_back(buffer_size);
|
||||
available_sizes_.push_back(0);
|
||||
row_bytes_.push_back(row_bytes);
|
||||
}
|
||||
|
||||
std::size_t FakeBufferModel::available_space() const
|
||||
{
|
||||
if (sizes_.empty())
|
||||
throw SaneException("Model has not been setup");
|
||||
return sizes_.front() - available_sizes_.front();
|
||||
}
|
||||
|
||||
void FakeBufferModel::simulate_read(std::size_t size)
|
||||
{
|
||||
if (sizes_.empty()) {
|
||||
throw SaneException("Model has not been setup");
|
||||
}
|
||||
if (available_space() < size) {
|
||||
throw SaneException("Attempted to simulate read of too much memory");
|
||||
}
|
||||
|
||||
available_sizes_.front() += size;
|
||||
|
||||
for (unsigned i = 1; i < sizes_.size(); ++i) {
|
||||
auto avail_src = available_sizes_[i - 1];
|
||||
auto avail_dst = sizes_[i] - available_sizes_[i];
|
||||
|
||||
auto avail = (std::min(avail_src, avail_dst) / row_bytes_[i]) * row_bytes_[i];
|
||||
available_sizes_[i - 1] -= avail;
|
||||
available_sizes_[i] += avail;
|
||||
}
|
||||
available_sizes_.back() = 0;
|
||||
}
|
||||
|
||||
ImageBufferGenesysUsb::ImageBufferGenesysUsb(std::size_t total_size,
|
||||
const FakeBufferModel& buffer_model,
|
||||
std::size_t buffer_size,
|
||||
ProducerCallback producer) :
|
||||
remaining_size_{total_size},
|
||||
buffer_model_{buffer_model},
|
||||
buffer_size_{buffer_size},
|
||||
producer_{producer}
|
||||
{}
|
||||
|
||||
|
@ -179,7 +143,7 @@ bool ImageBufferGenesysUsb::get_data(std::size_t size, std::uint8_t* out_data)
|
|||
|
||||
std::size_t ImageBufferGenesysUsb::get_read_size()
|
||||
{
|
||||
std::size_t size = buffer_model_.available_space();
|
||||
std::size_t size = buffer_size_;
|
||||
|
||||
// never read an odd number. exception: last read
|
||||
// the chip internal counter does not count half words.
|
||||
|
@ -195,8 +159,6 @@ std::size_t ImageBufferGenesysUsb::get_read_size()
|
|||
size &= ~0xff;
|
||||
}
|
||||
|
||||
buffer_model_.simulate_read(size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,23 +73,6 @@ private:
|
|||
std::vector<std::uint8_t> buffer_;
|
||||
};
|
||||
|
||||
class FakeBufferModel
|
||||
{
|
||||
public:
|
||||
FakeBufferModel() {}
|
||||
|
||||
void push_step(std::size_t buffer_size, std::size_t row_bytes);
|
||||
|
||||
std::size_t available_space() const;
|
||||
|
||||
void simulate_read(std::size_t size);
|
||||
|
||||
private:
|
||||
std::vector<std::size_t> sizes_;
|
||||
std::vector<std::size_t> available_sizes_;
|
||||
std::vector<std::size_t> row_bytes_;
|
||||
};
|
||||
|
||||
// This class is similar to ImageBuffer, but preserves historical peculiarities of buffer handling
|
||||
// in the backend to preserve exact behavior
|
||||
class ImageBufferGenesysUsb
|
||||
|
@ -98,7 +81,7 @@ public:
|
|||
using ProducerCallback = std::function<void(std::size_t size, std::uint8_t* out_data)>;
|
||||
|
||||
ImageBufferGenesysUsb() {}
|
||||
ImageBufferGenesysUsb(std::size_t total_size, const FakeBufferModel& buffer_model,
|
||||
ImageBufferGenesysUsb(std::size_t total_size, std::size_t buffer_size,
|
||||
ProducerCallback producer);
|
||||
|
||||
std::size_t remaining_size() const { return remaining_size_; }
|
||||
|
@ -115,12 +98,12 @@ private:
|
|||
|
||||
std::size_t remaining_size_ = 0;
|
||||
|
||||
std::size_t buffer_size_ = 0;
|
||||
|
||||
std::size_t buffer_offset_ = 0;
|
||||
std::size_t buffer_end_ = 0;
|
||||
std::vector<std::uint8_t> buffer_;
|
||||
|
||||
FakeBufferModel buffer_model_;
|
||||
|
||||
ProducerCallback producer_;
|
||||
};
|
||||
|
||||
|
|
|
@ -109,11 +109,11 @@ bool ImagePipelineNodeBufferedCallableSource::get_next_row_data(std::uint8_t* ou
|
|||
|
||||
ImagePipelineNodeBufferedGenesysUsb::ImagePipelineNodeBufferedGenesysUsb(
|
||||
std::size_t width, std::size_t height, PixelFormat format, std::size_t total_size,
|
||||
const FakeBufferModel& buffer_model, ProducerCallback producer) :
|
||||
std::size_t buffer_size, ProducerCallback producer) :
|
||||
width_{width},
|
||||
height_{height},
|
||||
format_{format},
|
||||
buffer_{total_size, buffer_model, producer}
|
||||
buffer_{total_size, buffer_size, producer}
|
||||
{
|
||||
set_remaining_bytes(total_size);
|
||||
}
|
||||
|
@ -319,6 +319,49 @@ bool ImagePipelineNodeSwap16BitEndian::get_next_row_data(std::uint8_t* out_data)
|
|||
return got_data;
|
||||
}
|
||||
|
||||
ImagePipelineNodeInvert::ImagePipelineNodeInvert(ImagePipelineNode& source) :
|
||||
source_(source)
|
||||
{
|
||||
}
|
||||
|
||||
bool ImagePipelineNodeInvert::get_next_row_data(std::uint8_t* out_data)
|
||||
{
|
||||
bool got_data = source_.get_next_row_data(out_data);
|
||||
auto num_values = get_width() * get_pixel_channels(source_.get_format());
|
||||
auto depth = get_pixel_format_depth(source_.get_format());
|
||||
|
||||
switch (depth) {
|
||||
case 16: {
|
||||
auto* data = reinterpret_cast<std::uint16_t*>(out_data);
|
||||
for (std::size_t i = 0; i < num_values; ++i) {
|
||||
*data = 0xffff - *data;
|
||||
data++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
auto* data = out_data;
|
||||
for (std::size_t i = 0; i < num_values; ++i) {
|
||||
*data = 0xff - *data;
|
||||
data++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
auto* data = out_data;
|
||||
for (std::size_t i = 0; i < num_values; ++i) {
|
||||
*data = ~*data;
|
||||
data++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw SaneException("Unsupported pixel depth");
|
||||
}
|
||||
|
||||
return got_data;
|
||||
}
|
||||
|
||||
ImagePipelineNodeMergeMonoLines::ImagePipelineNodeMergeMonoLines(ImagePipelineNode& source,
|
||||
ColorOrder color_order) :
|
||||
source_(source),
|
||||
|
@ -666,16 +709,21 @@ bool ImagePipelineNodeExtract::get_next_row_data(std::uint8_t* out_data)
|
|||
|
||||
ImagePipelineNodeCalibrate::ImagePipelineNodeCalibrate(ImagePipelineNode& source,
|
||||
const std::vector<std::uint16_t>& bottom,
|
||||
const std::vector<std::uint16_t>& top) :
|
||||
const std::vector<std::uint16_t>& top,
|
||||
std::size_t x_start) :
|
||||
source_{source}
|
||||
{
|
||||
auto size = std::min(bottom.size(), top.size());
|
||||
std::size_t size = 0;
|
||||
if (bottom.size() >= x_start && top.size() >= x_start) {
|
||||
size = std::min(bottom.size() - x_start, top.size() - x_start);
|
||||
}
|
||||
|
||||
offset_.reserve(size);
|
||||
multiplier_.reserve(size);
|
||||
|
||||
for (std::size_t i = 0; i < size; ++i) {
|
||||
offset_.push_back(bottom[i] / 65535.0f);
|
||||
multiplier_.push_back(65535.0f / (top[i] - bottom[i]));
|
||||
offset_.push_back(bottom[i + x_start] / 65535.0f);
|
||||
multiplier_.push_back(65535.0f / (top[i + x_start] - bottom[i + x_start]));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -157,8 +157,7 @@ public:
|
|||
|
||||
ImagePipelineNodeBufferedGenesysUsb(std::size_t width, std::size_t height,
|
||||
PixelFormat format, std::size_t total_size,
|
||||
const FakeBufferModel& buffer_model,
|
||||
ProducerCallback producer);
|
||||
std::size_t buffer_size, ProducerCallback producer);
|
||||
|
||||
std::size_t get_width() const override { return width_; }
|
||||
std::size_t get_height() const override { return height_; }
|
||||
|
@ -302,7 +301,7 @@ public:
|
|||
std::size_t pixels_per_chunk);
|
||||
};
|
||||
|
||||
// A pipeline that swaps bytes in 16-bit components on big-endian systems
|
||||
// A pipeline that swaps bytes in 16-bit components and does nothing otherwise.
|
||||
class ImagePipelineNodeSwap16BitEndian : public ImagePipelineNode
|
||||
{
|
||||
public:
|
||||
|
@ -321,6 +320,23 @@ private:
|
|||
bool needs_swapping_ = false;
|
||||
};
|
||||
|
||||
class ImagePipelineNodeInvert : public ImagePipelineNode
|
||||
{
|
||||
public:
|
||||
ImagePipelineNodeInvert(ImagePipelineNode& source);
|
||||
|
||||
std::size_t get_width() const override { return source_.get_width(); }
|
||||
std::size_t get_height() const override { return source_.get_height(); }
|
||||
PixelFormat get_format() const override { return source_.get_format(); }
|
||||
|
||||
bool eof() const override { return source_.eof(); }
|
||||
|
||||
bool get_next_row_data(std::uint8_t* out_data) override;
|
||||
|
||||
private:
|
||||
ImagePipelineNode& source_;
|
||||
};
|
||||
|
||||
// A pipeline node that merges 3 mono lines into a color channel
|
||||
class ImagePipelineNodeMergeMonoLines : public ImagePipelineNode
|
||||
{
|
||||
|
@ -476,7 +492,7 @@ class ImagePipelineNodeCalibrate : public ImagePipelineNode
|
|||
public:
|
||||
|
||||
ImagePipelineNodeCalibrate(ImagePipelineNode& source, const std::vector<std::uint16_t>& bottom,
|
||||
const std::vector<std::uint16_t>& top);
|
||||
const std::vector<std::uint16_t>& top, std::size_t x_start);
|
||||
|
||||
std::size_t get_width() const override { return source_.get_width(); }
|
||||
std::size_t get_height() const override { return source_.get_height(); }
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
|
||||
namespace genesys {
|
||||
|
||||
// 16-bit values are in host endian
|
||||
enum class PixelFormat
|
||||
{
|
||||
UNKNOWN,
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -108,39 +108,6 @@
|
|||
#define GENESYS_GREEN 1
|
||||
#define GENESYS_BLUE 2
|
||||
|
||||
/* Flags */
|
||||
#define GENESYS_FLAG_UNTESTED (1 << 0) /**< Print a warning for these scanners */
|
||||
#define GENESYS_FLAG_14BIT_GAMMA (1 << 1) /**< use 14bit Gamma table instead of 12 */
|
||||
#define GENESYS_FLAG_XPA (1 << 3)
|
||||
#define GENESYS_FLAG_SKIP_WARMUP (1 << 4) /**< skip genesys_warmup() */
|
||||
/** @brief offset calibration flag
|
||||
* signals that the scanner does offset calibration. In this case off_calibration() and
|
||||
* coarse_gain_calibration() functions must be implemented
|
||||
*/
|
||||
#define GENESYS_FLAG_OFFSET_CALIBRATION (1 << 5)
|
||||
#define GENESYS_FLAG_SEARCH_START (1 << 6) /**< do start search before scanning */
|
||||
#define GENESYS_FLAG_REPARK (1 << 7) /**< repark head (and check for lock) by
|
||||
moving without scanning */
|
||||
#define GENESYS_FLAG_DARK_CALIBRATION (1 << 8) /**< do dark calibration */
|
||||
|
||||
#define GENESYS_FLAG_MUST_WAIT (1 << 10) /**< tells wether the scanner must wait for the head when parking */
|
||||
|
||||
|
||||
#define GENESYS_FLAG_HAS_UTA (1 << 11) /**< scanner has a transparency adapter */
|
||||
|
||||
#define GENESYS_FLAG_DARK_WHITE_CALIBRATION (1 << 12) /**< yet another calibration method. does white and dark shading in one run, depending on a black and a white strip*/
|
||||
#define GENESYS_FLAG_CUSTOM_GAMMA (1 << 13) /**< allow custom gamma tables */
|
||||
#define GENESYS_FLAG_NO_CALIBRATION (1 << 14) /**< allow scanners to use skip the calibration, needed for sheetfed scanners */
|
||||
#define GENESYS_FLAG_SIS_SENSOR (1 << 16) /**< handling of multi-segments sensors in software */
|
||||
#define GENESYS_FLAG_SHADING_NO_MOVE (1 << 17) /**< scanner doesn't move sensor during shading calibration */
|
||||
#define GENESYS_FLAG_SHADING_REPARK (1 << 18) /**< repark head between shading scans */
|
||||
#define GENESYS_FLAG_FULL_HWDPI_MODE (1 << 19) /**< scanner always use maximum hw dpi to setup the sensor */
|
||||
// scanner has infrared transparency scanning capability
|
||||
#define GENESYS_FLAG_HAS_UTA_INFRARED (1 << 20)
|
||||
// scanner calibration is handled on the host side
|
||||
#define GENESYS_FLAG_CALIBRATION_HOST_SIDE (1 << 21)
|
||||
#define GENESYS_FLAG_16BIT_DATA_INVERTED (1 << 22)
|
||||
|
||||
#define GENESYS_HAS_NO_BUTTONS 0 /**< scanner has no supported button */
|
||||
#define GENESYS_HAS_SCAN_SW (1 << 0) /**< scanner has SCAN button */
|
||||
#define GENESYS_HAS_FILE_SW (1 << 1) /**< scanner has FILE button */
|
||||
|
@ -186,66 +153,60 @@
|
|||
#define AFE_SET 2
|
||||
#define AFE_POWER_SAVE 4
|
||||
|
||||
#define LOWORD(x) ((uint16_t)((x) & 0xffff))
|
||||
#define HIWORD(x) ((uint16_t)((x) >> 16))
|
||||
#define LOBYTE(x) ((uint8_t)((x) & 0xFF))
|
||||
#define HIBYTE(x) ((uint8_t)((x) >> 8))
|
||||
|
||||
/* Global constants */
|
||||
/* TODO: emove this leftover of early backend days */
|
||||
#define MOTOR_SPEED_MAX 350
|
||||
#define DARK_VALUE 0
|
||||
|
||||
#define MAX_RESOLUTIONS 13
|
||||
#define MAX_DPI 4
|
||||
|
||||
namespace genesys {
|
||||
|
||||
struct Genesys_USB_Device_Entry {
|
||||
class UsbDeviceEntry {
|
||||
public:
|
||||
static constexpr std::uint16_t BCD_DEVICE_NOT_SET = 0xffff;
|
||||
|
||||
Genesys_USB_Device_Entry(unsigned v, unsigned p, const Genesys_Model& m) :
|
||||
vendor(v), product(p), model(m)
|
||||
UsbDeviceEntry(std::uint16_t vendor_id, std::uint16_t product_id,
|
||||
const Genesys_Model& model) :
|
||||
vendor_{vendor_id}, product_{product_id},
|
||||
bcd_device_{BCD_DEVICE_NOT_SET}, model_{model}
|
||||
{}
|
||||
|
||||
UsbDeviceEntry(std::uint16_t vendor_id, std::uint16_t product_id, std::uint16_t bcd_device,
|
||||
const Genesys_Model& model) :
|
||||
vendor_{vendor_id}, product_{product_id},
|
||||
bcd_device_{bcd_device}, model_{model}
|
||||
{}
|
||||
|
||||
std::uint16_t vendor_id() const { return vendor_; }
|
||||
std::uint16_t product_id() const { return product_; }
|
||||
std::uint16_t bcd_device() const { return bcd_device_; }
|
||||
|
||||
const Genesys_Model& model() const { return model_; }
|
||||
|
||||
bool matches(std::uint16_t vendor_id, std::uint16_t product_id, std::uint16_t bcd_device)
|
||||
{
|
||||
if (vendor_ != vendor_id)
|
||||
return false;
|
||||
if (product_ != product_id)
|
||||
return false;
|
||||
if (bcd_device_ != BCD_DEVICE_NOT_SET && bcd_device != BCD_DEVICE_NOT_SET &&
|
||||
bcd_device_ != bcd_device)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// USB vendor identifier
|
||||
std::uint16_t vendor;
|
||||
std::uint16_t vendor_;
|
||||
// USB product identifier
|
||||
std::uint16_t product;
|
||||
std::uint16_t product_;
|
||||
// USB bcdProduct identifier
|
||||
std::uint16_t bcd_device_;
|
||||
// Scanner model information
|
||||
Genesys_Model model;
|
||||
Genesys_Model model_;
|
||||
};
|
||||
|
||||
/**
|
||||
* structure for motor database
|
||||
*/
|
||||
struct Motor_Profile
|
||||
{
|
||||
MotorId motor_id;
|
||||
int exposure; // used only to select the wanted motor
|
||||
StepType step_type; // default step type for given exposure
|
||||
MotorSlope slope;
|
||||
};
|
||||
|
||||
extern StaticInit<std::vector<Motor_Profile>> gl843_motor_profiles;
|
||||
extern StaticInit<std::vector<Motor_Profile>> gl846_motor_profiles;
|
||||
extern StaticInit<std::vector<Motor_Profile>> gl847_motor_profiles;
|
||||
extern StaticInit<std::vector<Motor_Profile>> gl124_motor_profiles;
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* common functions needed by low level specific functions */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
inline GenesysRegister* sanei_genesys_get_address(Genesys_Register_Set* regs, uint16_t addr)
|
||||
{
|
||||
auto* ret = regs->find_reg_address(addr);
|
||||
if (ret == nullptr) {
|
||||
DBG(DBG_error, "%s: failed to find address for register 0x%02x, crash expected !\n",
|
||||
__func__, addr);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern void sanei_genesys_init_cmd_set(Genesys_Device* dev);
|
||||
std::unique_ptr<CommandSet> create_cmd_set(AsicType asic_type);
|
||||
|
||||
// reads the status of the scanner
|
||||
Status scanner_read_status(Genesys_Device& dev);
|
||||
|
@ -318,13 +279,9 @@ extern void sanei_genesys_set_buffer_address(Genesys_Device* dev, uint32_t addr)
|
|||
|
||||
unsigned sanei_genesys_get_bulk_max_size(AsicType asic_type);
|
||||
|
||||
SANE_Int sanei_genesys_exposure_time2(Genesys_Device * dev, float ydpi, StepType step_type,
|
||||
SANE_Int sanei_genesys_exposure_time2(Genesys_Device* dev, const MotorProfile& profile, float ydpi,
|
||||
int endpixel, int led_exposure);
|
||||
|
||||
MotorSlopeTable sanei_genesys_create_slope_table3(AsicType asic_type, const Genesys_Motor& motor,
|
||||
StepType step_type, int exposure_time,
|
||||
unsigned yres);
|
||||
|
||||
void sanei_genesys_create_default_gamma_table(Genesys_Device* dev,
|
||||
std::vector<uint16_t>& gamma_table, float gamma);
|
||||
|
||||
|
@ -335,18 +292,40 @@ void sanei_genesys_send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& s
|
|||
|
||||
extern void sanei_genesys_stop_motor(Genesys_Device* dev);
|
||||
|
||||
extern void sanei_genesys_search_reference_point(Genesys_Device* dev, Genesys_Sensor& sensor,
|
||||
const uint8_t* src_data, int start_pixel, int dpi,
|
||||
int width, int height);
|
||||
|
||||
// moves the scan head by the specified steps at the motor base dpi
|
||||
void scanner_move(Genesys_Device& dev, ScanMethod scan_method, unsigned steps, Direction direction);
|
||||
|
||||
void scanner_move_back_home(Genesys_Device& dev, bool wait_until_home);
|
||||
void scanner_move_back_home_ta(Genesys_Device& dev);
|
||||
|
||||
/** Search for a full width black or white strip.
|
||||
This function searches for a black or white stripe across the scanning area.
|
||||
When searching backward, the searched area must completely be of the desired
|
||||
color since this area will be used for calibration which scans forward.
|
||||
|
||||
@param dev scanner device
|
||||
@param forward true if searching forward, false if searching backward
|
||||
@param black true if searching for a black strip, false for a white strip
|
||||
*/
|
||||
void scanner_search_strip(Genesys_Device& dev, bool forward, bool black);
|
||||
|
||||
bool should_calibrate_only_active_area(const Genesys_Device& dev,
|
||||
const Genesys_Settings& settings);
|
||||
|
||||
void scanner_offset_calibration(Genesys_Device& dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs);
|
||||
|
||||
void scanner_coarse_gain_calibration(Genesys_Device& dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs, unsigned dpi);
|
||||
|
||||
SensorExposure scanner_led_calibration(Genesys_Device& dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs);
|
||||
|
||||
void scanner_clear_scan_and_feed_counts(Genesys_Device& dev);
|
||||
|
||||
void scanner_send_slope_table(Genesys_Device* dev, const Genesys_Sensor& sensor, unsigned table_nr,
|
||||
const std::vector<uint16_t>& slope_table);
|
||||
|
||||
extern void sanei_genesys_write_file(const char* filename, const std::uint8_t* data,
|
||||
std::size_t length);
|
||||
|
||||
|
@ -370,25 +349,13 @@ void regs_set_exposure(AsicType asic_type, Genesys_Register_Set& regs,
|
|||
|
||||
void regs_set_optical_off(AsicType asic_type, Genesys_Register_Set& regs);
|
||||
|
||||
void sanei_genesys_set_dpihw(Genesys_Register_Set& regs, const Genesys_Sensor& sensor,
|
||||
unsigned dpihw);
|
||||
|
||||
inline uint16_t sanei_genesys_fixup_exposure_value(uint16_t value)
|
||||
{
|
||||
if ((value & 0xff00) == 0) {
|
||||
value |= 0x100;
|
||||
}
|
||||
if ((value & 0x00ff) == 0) {
|
||||
value |= 0x1;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
void sanei_genesys_set_dpihw(Genesys_Register_Set& regs, unsigned dpihw);
|
||||
|
||||
inline SensorExposure sanei_genesys_fixup_exposure(SensorExposure exposure)
|
||||
{
|
||||
exposure.red = sanei_genesys_fixup_exposure_value(exposure.red);
|
||||
exposure.green = sanei_genesys_fixup_exposure_value(exposure.green);
|
||||
exposure.blue = sanei_genesys_fixup_exposure_value(exposure.blue);
|
||||
exposure.red = std::max<std::uint16_t>(1, exposure.red);
|
||||
exposure.green = std::max<std::uint16_t>(1, exposure.green);
|
||||
exposure.blue = std::max<std::uint16_t>(1, exposure.blue);
|
||||
return exposure;
|
||||
}
|
||||
|
||||
|
@ -396,7 +363,7 @@ bool get_registers_gain4_bit(AsicType asic_type, const Genesys_Register_Set& reg
|
|||
|
||||
extern void sanei_genesys_wait_for_home(Genesys_Device* dev);
|
||||
|
||||
extern void sanei_genesys_asic_init(Genesys_Device* dev, bool cold);
|
||||
extern void sanei_genesys_asic_init(Genesys_Device* dev);
|
||||
|
||||
void scanner_start_action(Genesys_Device& dev, bool start_motor);
|
||||
void scanner_stop_action(Genesys_Device& dev);
|
||||
|
@ -404,15 +371,23 @@ void scanner_stop_action_no_move(Genesys_Device& dev, Genesys_Register_Set& regs
|
|||
|
||||
bool scanner_is_motor_stopped(Genesys_Device& dev);
|
||||
|
||||
const Motor_Profile& sanei_genesys_get_motor_profile(const std::vector<Motor_Profile>& motors,
|
||||
MotorId motor_id, int exposure);
|
||||
void scanner_setup_sensor(Genesys_Device& dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs);
|
||||
|
||||
MotorSlopeTable sanei_genesys_slope_table(AsicType asic_type, int dpi, int exposure, int base_dpi,
|
||||
unsigned step_multiplier,
|
||||
const Motor_Profile& motor_profile);
|
||||
const MotorProfile* get_motor_profile_ptr(const std::vector<MotorProfile>& profiles,
|
||||
unsigned exposure,
|
||||
const ScanSession& session);
|
||||
|
||||
const MotorProfile& get_motor_profile(const std::vector<MotorProfile>& profiles,
|
||||
unsigned exposure,
|
||||
const ScanSession& session);
|
||||
|
||||
MotorSlopeTable create_slope_table(AsicType asic_type, const Genesys_Motor& motor, unsigned ydpi,
|
||||
unsigned exposure, unsigned step_multiplier,
|
||||
const MotorProfile& motor_profile);
|
||||
|
||||
MotorSlopeTable create_slope_table_fastest(AsicType asic_type, unsigned step_multiplier,
|
||||
const Motor_Profile& motor_profile);
|
||||
const MotorProfile& motor_profile);
|
||||
|
||||
/** @brief find lowest motor resolution for the device.
|
||||
* Parses the resolution list for motor and
|
||||
|
@ -502,15 +477,18 @@ inline T clamp(const T& value, const T& lo, const T& hi)
|
|||
extern StaticInit<std::vector<Genesys_Sensor>> s_sensors;
|
||||
extern StaticInit<std::vector<Genesys_Frontend>> s_frontends;
|
||||
extern StaticInit<std::vector<Genesys_Gpo>> s_gpo;
|
||||
extern StaticInit<std::vector<MemoryLayout>> s_memory_layout;
|
||||
extern StaticInit<std::vector<Genesys_Motor>> s_motors;
|
||||
extern StaticInit<std::vector<Genesys_USB_Device_Entry>> s_usb_devices;
|
||||
extern StaticInit<std::vector<UsbDeviceEntry>> s_usb_devices;
|
||||
|
||||
void genesys_init_sensor_tables();
|
||||
void genesys_init_frontend_tables();
|
||||
void genesys_init_gpo_tables();
|
||||
void genesys_init_memory_layout_tables();
|
||||
void genesys_init_motor_tables();
|
||||
void genesys_init_motor_profile_tables();
|
||||
void genesys_init_usb_device_tables();
|
||||
void verify_sensor_tables();
|
||||
void verify_usb_device_tables();
|
||||
|
||||
template<class T>
|
||||
void debug_dump(unsigned level, const T& value)
|
||||
|
|
|
@ -43,9 +43,11 @@
|
|||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
|
||||
#include "low.h"
|
||||
#include "motor.h"
|
||||
#include "utilities.h"
|
||||
#include <cmath>
|
||||
#include <numeric>
|
||||
|
||||
namespace genesys {
|
||||
|
||||
|
@ -80,19 +82,38 @@ MotorSlope MotorSlope::create_from_steps(unsigned initial_w, unsigned max_w,
|
|||
return slope;
|
||||
}
|
||||
|
||||
void MotorSlopeTable::slice_steps(unsigned count)
|
||||
void MotorSlopeTable::slice_steps(unsigned count, unsigned step_multiplier)
|
||||
{
|
||||
if (count >= table.size() || count > steps_count) {
|
||||
throw SaneException("Excepssive steps count");
|
||||
if (count > table.size() || count < step_multiplier) {
|
||||
throw SaneException("Invalid steps count");
|
||||
}
|
||||
steps_count = count;
|
||||
count = align_multiple_floor(count, step_multiplier);
|
||||
table.resize(count);
|
||||
generate_pixeltime_sum();
|
||||
}
|
||||
|
||||
void MotorSlopeTable::expand_table(unsigned count, unsigned step_multiplier)
|
||||
{
|
||||
if (table.empty()) {
|
||||
throw SaneException("Can't expand empty table");
|
||||
}
|
||||
count = align_multiple_ceil(count, step_multiplier);
|
||||
table.resize(table.size() + count, table.back());
|
||||
generate_pixeltime_sum();
|
||||
}
|
||||
|
||||
void MotorSlopeTable::generate_pixeltime_sum()
|
||||
{
|
||||
pixeltime_sum_ = std::accumulate(table.begin(), table.end(),
|
||||
std::size_t{0}, std::plus<std::size_t>());
|
||||
}
|
||||
|
||||
unsigned get_slope_table_max_size(AsicType asic_type)
|
||||
{
|
||||
switch (asic_type) {
|
||||
case AsicType::GL646:
|
||||
case AsicType::GL841: return 255;
|
||||
case AsicType::GL841:
|
||||
case AsicType::GL842: return 255;
|
||||
case AsicType::GL843:
|
||||
case AsicType::GL845:
|
||||
case AsicType::GL846:
|
||||
|
@ -103,9 +124,9 @@ unsigned get_slope_table_max_size(AsicType asic_type)
|
|||
}
|
||||
}
|
||||
|
||||
MotorSlopeTable create_slope_table(const MotorSlope& slope, unsigned target_speed_w,
|
||||
StepType step_type, unsigned steps_alignment,
|
||||
unsigned min_size, unsigned max_size)
|
||||
MotorSlopeTable create_slope_table_for_speed(const MotorSlope& slope, unsigned target_speed_w,
|
||||
StepType step_type, unsigned steps_alignment,
|
||||
unsigned min_size, unsigned max_size)
|
||||
{
|
||||
DBG_HELPER_ARGS(dbg, "target_speed_w: %d, step_type: %d, steps_alignment: %d, min_size: %d",
|
||||
target_speed_w, static_cast<unsigned>(step_type), steps_alignment, min_size);
|
||||
|
@ -130,26 +151,20 @@ MotorSlopeTable create_slope_table(const MotorSlope& slope, unsigned target_spee
|
|||
break;
|
||||
}
|
||||
table.table.push_back(current);
|
||||
table.pixeltime_sum += current;
|
||||
}
|
||||
|
||||
// make sure the target speed (or the max speed if target speed is too high) is present in
|
||||
// the table
|
||||
table.table.push_back(final_speed);
|
||||
table.pixeltime_sum += table.table.back();
|
||||
|
||||
// fill the table up to the specified size
|
||||
while (table.table.size() < max_size - 1 &&
|
||||
(table.table.size() % steps_alignment != 0 || table.table.size() < min_size))
|
||||
{
|
||||
table.table.push_back(table.table.back());
|
||||
table.pixeltime_sum += table.table.back();
|
||||
}
|
||||
|
||||
table.steps_count = table.table.size();
|
||||
|
||||
// fill the rest of the table with the final speed
|
||||
table.table.resize(max_size, final_speed);
|
||||
table.generate_pixeltime_sum();
|
||||
|
||||
return table;
|
||||
}
|
||||
|
@ -164,15 +179,30 @@ std::ostream& operator<<(std::ostream& out, const MotorSlope& slope)
|
|||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const MotorProfile& profile)
|
||||
{
|
||||
out << "MotorProfile{\n"
|
||||
<< " max_exposure: " << profile.max_exposure << '\n'
|
||||
<< " step_type: " << profile.step_type << '\n'
|
||||
<< " motor_vref: " << profile.motor_vref << '\n'
|
||||
<< " resolutions: " << format_indent_braced_list(4, profile.resolutions) << '\n'
|
||||
<< " scan_methods: " << format_indent_braced_list(4, profile.scan_methods) << '\n'
|
||||
<< " slope: " << format_indent_braced_list(4, profile.slope) << '\n'
|
||||
<< '}';
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const Genesys_Motor& motor)
|
||||
{
|
||||
out << "Genesys_Motor{\n"
|
||||
<< " id: " << static_cast<unsigned>(motor.id) << '\n'
|
||||
<< " id: " << motor.id << '\n'
|
||||
<< " base_ydpi: " << motor.base_ydpi << '\n'
|
||||
<< " optical_ydpi: " << motor.optical_ydpi << '\n'
|
||||
<< " slopes: "
|
||||
<< format_indent_braced_list(4, format_vector_indent_braced(4, "MotorSlope",
|
||||
motor.slopes))
|
||||
<< " profiles: "
|
||||
<< format_indent_braced_list(4, format_vector_indent_braced(4, "MotorProfile",
|
||||
motor.profiles)) << '\n'
|
||||
<< " fast_profiles: "
|
||||
<< format_indent_braced_list(4, format_vector_indent_braced(4, "MotorProfile",
|
||||
motor.fast_profiles)) << '\n'
|
||||
<< '}';
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -44,9 +44,12 @@
|
|||
#ifndef BACKEND_GENESYS_MOTOR_H
|
||||
#define BACKEND_GENESYS_MOTOR_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include "enums.h"
|
||||
#include "sensor.h"
|
||||
#include "value_filter.h"
|
||||
|
||||
namespace genesys {
|
||||
|
||||
|
@ -123,20 +126,47 @@ struct MotorSlope
|
|||
struct MotorSlopeTable
|
||||
{
|
||||
std::vector<std::uint16_t> table;
|
||||
unsigned steps_count = 0;
|
||||
unsigned pixeltime_sum = 0;
|
||||
|
||||
void slice_steps(unsigned count);
|
||||
void slice_steps(unsigned count, unsigned step_multiplier);
|
||||
|
||||
// expands the table by the given number of steps
|
||||
void expand_table(unsigned count, unsigned step_multiplier);
|
||||
|
||||
std::uint64_t pixeltime_sum() const { return pixeltime_sum_; }
|
||||
|
||||
void generate_pixeltime_sum();
|
||||
private:
|
||||
std::uint64_t pixeltime_sum_ = 0;
|
||||
};
|
||||
|
||||
unsigned get_slope_table_max_size(AsicType asic_type);
|
||||
|
||||
MotorSlopeTable create_slope_table(const MotorSlope& slope, unsigned target_speed_w,
|
||||
StepType step_type, unsigned steps_alignment,
|
||||
unsigned min_size, unsigned max_size);
|
||||
MotorSlopeTable create_slope_table_for_speed(const MotorSlope& slope, unsigned target_speed_w,
|
||||
StepType step_type, unsigned steps_alignment,
|
||||
unsigned min_size, unsigned max_size);
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const MotorSlope& slope);
|
||||
|
||||
struct MotorProfile
|
||||
{
|
||||
MotorProfile() = default;
|
||||
MotorProfile(const MotorSlope& a_slope, StepType a_step_type, unsigned a_max_exposure) :
|
||||
slope{a_slope}, step_type{a_step_type}, max_exposure{a_max_exposure}
|
||||
{}
|
||||
|
||||
MotorSlope slope;
|
||||
StepType step_type = StepType::FULL;
|
||||
int motor_vref = -1;
|
||||
|
||||
// the resolutions this profile is good for
|
||||
ValueFilterAny<unsigned> resolutions = VALUE_FILTER_ANY;
|
||||
// the scan method this profile is good for. If the list is empty, good for any method.
|
||||
ValueFilterAny<ScanMethod> scan_methods = VALUE_FILTER_ANY;
|
||||
|
||||
unsigned max_exposure = 0; // 0 - any exposure
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const MotorProfile& profile);
|
||||
|
||||
struct Genesys_Motor
|
||||
{
|
||||
|
@ -146,27 +176,41 @@ struct Genesys_Motor
|
|||
MotorId id = MotorId::UNKNOWN;
|
||||
// motor base steps. Unit: 1/inch
|
||||
int base_ydpi = 0;
|
||||
// maximum resolution in y-direction. Unit: 1/inch
|
||||
int optical_ydpi = 0;
|
||||
// slopes to derive individual slopes from
|
||||
std::vector<MotorSlope> slopes;
|
||||
std::vector<MotorProfile> profiles;
|
||||
// slopes to derive individual slopes from for fast moving
|
||||
std::vector<MotorProfile> fast_profiles;
|
||||
|
||||
MotorSlope& get_slope(StepType step_type)
|
||||
MotorSlope& get_slope_with_step_type(StepType step_type)
|
||||
{
|
||||
return slopes[static_cast<unsigned>(step_type)];
|
||||
for (auto& p : profiles) {
|
||||
if (p.step_type == step_type)
|
||||
return p.slope;
|
||||
}
|
||||
throw SaneException("No motor profile with step type");
|
||||
}
|
||||
|
||||
const MotorSlope& get_slope(StepType step_type) const
|
||||
const MotorSlope& get_slope_with_step_type(StepType step_type) const
|
||||
{
|
||||
return slopes[static_cast<unsigned>(step_type)];
|
||||
for (const auto& p : profiles) {
|
||||
if (p.step_type == step_type)
|
||||
return p.slope;
|
||||
}
|
||||
throw SaneException("No motor profile with step type");
|
||||
}
|
||||
|
||||
StepType max_step_type() const
|
||||
{
|
||||
if (slopes.empty()) {
|
||||
throw std::runtime_error("Slopes table is empty");
|
||||
if (profiles.empty()) {
|
||||
throw std::runtime_error("Profiles table is empty");
|
||||
}
|
||||
return static_cast<StepType>(slopes.size() - 1);
|
||||
StepType step_type = StepType::FULL;
|
||||
for (const auto& p : profiles) {
|
||||
step_type = static_cast<StepType>(
|
||||
std::max(static_cast<unsigned>(step_type),
|
||||
static_cast<unsigned>(p.step_type)));
|
||||
}
|
||||
return step_type;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#ifndef BACKEND_GENESYS_REGISTER_H
|
||||
#define BACKEND_GENESYS_REGISTER_H
|
||||
|
||||
#include "enums.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -76,7 +77,7 @@ struct GenesysRegisterSetState
|
|||
bool is_lamp_on = false;
|
||||
bool is_xpa_on = false;
|
||||
bool is_motor_on = false;
|
||||
bool is_xpa_motor_on = false;
|
||||
MotorMode motor_mode = MotorMode::PRIMARY;
|
||||
};
|
||||
|
||||
template<class Value>
|
||||
|
@ -414,6 +415,11 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
bool has_reg(AddressType address) const
|
||||
{
|
||||
return find_reg_index(address) != -1;
|
||||
}
|
||||
|
||||
SettingType& find_reg(AddressType address)
|
||||
{
|
||||
int i = find_reg_index(address);
|
||||
|
|
|
@ -56,11 +56,6 @@ namespace genesys {
|
|||
class ScannerInterface
|
||||
{
|
||||
public:
|
||||
enum Flags {
|
||||
FLAG_NONE = 0,
|
||||
FLAG_SWAP_REGISTERS = 1 << 0,
|
||||
FLAG_SMALL_ADDRESS = 1 << 1
|
||||
};
|
||||
|
||||
virtual ~ScannerInterface();
|
||||
|
||||
|
@ -75,12 +70,11 @@ public:
|
|||
virtual void bulk_write_data(std::uint8_t addr, std::uint8_t* data, std::size_t size) = 0;
|
||||
|
||||
// GL646, GL841, GL843 have different ways to write to RAM and to gamma tables
|
||||
// FIXME: remove flags when updating tests
|
||||
virtual void write_buffer(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags = FLAG_NONE) = 0;
|
||||
std::size_t size) = 0;
|
||||
|
||||
virtual void write_gamma(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags = FLAG_NONE) = 0;
|
||||
std::size_t size) = 0;
|
||||
|
||||
// GL845, GL846, GL847 and GL124 have a uniform way to write to RAM tables
|
||||
virtual void write_ahb(std::uint32_t addr, std::uint32_t size, std::uint8_t* data) = 0;
|
||||
|
|
|
@ -101,8 +101,6 @@ std::uint8_t ScannerInterfaceUsb::read_register(std::uint16_t address)
|
|||
usb_dev_.control_msg(REQUEST_TYPE_IN, REQUEST_REGISTER, VALUE_READ_REGISTER, INDEX,
|
||||
1, &value);
|
||||
}
|
||||
|
||||
DBG(DBG_proc, "%s (0x%02x, 0x%02x) completed\n", __func__, address, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -213,6 +211,7 @@ static void bulk_read_data_send_header(UsbDevice& usb_dev, AsicType asic_type, s
|
|||
|
||||
uint8_t outdata[8];
|
||||
if (asic_type == AsicType::GL124 ||
|
||||
asic_type == AsicType::GL845 ||
|
||||
asic_type == AsicType::GL846 ||
|
||||
asic_type == AsicType::GL847)
|
||||
{
|
||||
|
@ -222,7 +221,9 @@ static void bulk_read_data_send_header(UsbDevice& usb_dev, AsicType asic_type, s
|
|||
outdata[2] = 0;
|
||||
outdata[3] = 0x10;
|
||||
} else if (asic_type == AsicType::GL841 ||
|
||||
asic_type == AsicType::GL843) {
|
||||
asic_type == AsicType::GL842 ||
|
||||
asic_type == AsicType::GL843)
|
||||
{
|
||||
outdata[0] = BULK_IN;
|
||||
outdata[1] = BULK_RAM;
|
||||
outdata[2] = 0x82; //
|
||||
|
@ -246,12 +247,13 @@ static void bulk_read_data_send_header(UsbDevice& usb_dev, AsicType asic_type, s
|
|||
|
||||
void ScannerInterfaceUsb::bulk_read_data(std::uint8_t addr, std::uint8_t* data, std::size_t size)
|
||||
{
|
||||
// currently supported: GL646, GL841, GL843, GL846, GL847, GL124
|
||||
// currently supported: GL646, GL841, GL843, GL845, GL846, GL847, GL124
|
||||
DBG_HELPER(dbg);
|
||||
|
||||
unsigned is_addr_used = 1;
|
||||
unsigned has_header_before_each_chunk = 0;
|
||||
if (dev_->model->asic_type == AsicType::GL124 ||
|
||||
dev_->model->asic_type == AsicType::GL845 ||
|
||||
dev_->model->asic_type == AsicType::GL846 ||
|
||||
dev_->model->asic_type == AsicType::GL847)
|
||||
{
|
||||
|
@ -351,30 +353,21 @@ void ScannerInterfaceUsb::bulk_write_data(std::uint8_t addr, std::uint8_t* data,
|
|||
}
|
||||
|
||||
void ScannerInterfaceUsb::write_buffer(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags)
|
||||
std::size_t size)
|
||||
{
|
||||
DBG_HELPER_ARGS(dbg, "type: 0x%02x, addr: 0x%08x, size: 0x%08zx", type, addr, size);
|
||||
if (dev_->model->asic_type != AsicType::GL646 &&
|
||||
dev_->model->asic_type != AsicType::GL841 &&
|
||||
dev_->model->asic_type != AsicType::GL842 &&
|
||||
dev_->model->asic_type != AsicType::GL843)
|
||||
{
|
||||
throw SaneException("Unsupported transfer mode");
|
||||
}
|
||||
|
||||
if (dev_->model->asic_type == AsicType::GL843) {
|
||||
if (flags & FLAG_SWAP_REGISTERS) {
|
||||
if (!(flags & FLAG_SMALL_ADDRESS)) {
|
||||
write_register(0x29, ((addr >> 20) & 0xff));
|
||||
}
|
||||
write_register(0x2a, ((addr >> 12) & 0xff));
|
||||
write_register(0x2b, ((addr >> 4) & 0xff));
|
||||
} else {
|
||||
write_register(0x2b, ((addr >> 4) & 0xff));
|
||||
write_register(0x2a, ((addr >> 12) & 0xff));
|
||||
if (!(flags & FLAG_SMALL_ADDRESS)) {
|
||||
write_register(0x29, ((addr >> 20) & 0xff));
|
||||
}
|
||||
}
|
||||
write_register(0x2b, ((addr >> 4) & 0xff));
|
||||
write_register(0x2a, ((addr >> 12) & 0xff));
|
||||
write_register(0x29, ((addr >> 20) & 0xff));
|
||||
} else {
|
||||
write_register(0x2b, ((addr >> 4) & 0xff));
|
||||
write_register(0x2a, ((addr >> 12) & 0xff));
|
||||
|
@ -383,24 +376,28 @@ void ScannerInterfaceUsb::write_buffer(std::uint8_t type, std::uint32_t addr, st
|
|||
}
|
||||
|
||||
void ScannerInterfaceUsb::write_gamma(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags)
|
||||
std::size_t size)
|
||||
{
|
||||
DBG_HELPER_ARGS(dbg, "type: 0x%02x, addr: 0x%08x, size: 0x%08zx", type, addr, size);
|
||||
if (dev_->model->asic_type != AsicType::GL646 &&
|
||||
dev_->model->asic_type != AsicType::GL841 &&
|
||||
if (dev_->model->asic_type != AsicType::GL841 &&
|
||||
dev_->model->asic_type != AsicType::GL842 &&
|
||||
dev_->model->asic_type != AsicType::GL843)
|
||||
{
|
||||
throw SaneException("Unsupported transfer mode");
|
||||
}
|
||||
|
||||
if (flags & FLAG_SWAP_REGISTERS) {
|
||||
write_register(0x5b, ((addr >> 12) & 0xff));
|
||||
write_register(0x5c, ((addr >> 4) & 0xff));
|
||||
} else {
|
||||
write_register(0x5c, ((addr >> 4) & 0xff));
|
||||
write_register(0x5b, ((addr >> 12) & 0xff));
|
||||
}
|
||||
write_register(0x5b, ((addr >> 12) & 0xff));
|
||||
write_register(0x5c, ((addr >> 4) & 0xff));
|
||||
bulk_write_data(type, data, size);
|
||||
|
||||
if (dev_->model->asic_type == AsicType::GL842 ||
|
||||
dev_->model->asic_type == AsicType::GL843)
|
||||
{
|
||||
// it looks like we need to reset the address so that subsequent buffer operations work.
|
||||
// Most likely the MTRTBL register is to blame.
|
||||
write_register(0x5b, 0);
|
||||
write_register(0x5c, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ScannerInterfaceUsb::write_ahb(std::uint32_t addr, std::uint32_t size, std::uint8_t* data)
|
||||
|
|
|
@ -67,9 +67,9 @@ public:
|
|||
void bulk_write_data(std::uint8_t addr, std::uint8_t* data, std::size_t size) override;
|
||||
|
||||
void write_buffer(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags) override;
|
||||
std::size_t size) override;
|
||||
void write_gamma(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags) override;
|
||||
std::size_t size) override;
|
||||
|
||||
void write_ahb(std::uint32_t addr, std::uint32_t size, std::uint8_t* data) override;
|
||||
|
||||
|
|
|
@ -64,6 +64,11 @@ std::ostream& operator<<(std::ostream& out, const FrontendType& type)
|
|||
case FrontendType::UNKNOWN: out << "UNKNOWN"; break;
|
||||
case FrontendType::WOLFSON: out << "WOLFSON"; break;
|
||||
case FrontendType::ANALOG_DEVICES: out << "ANALOG_DEVICES"; break;
|
||||
case FrontendType::CANON_LIDE_80: out << "CANON_LIDE_80"; break;
|
||||
case FrontendType::WOLFSON_GL841: out << "WOLFSON_GL841"; break;
|
||||
case FrontendType::WOLFSON_GL846: out << "WOLFSON_GL846"; break;
|
||||
case FrontendType::ANALOG_DEVICES_GL847: out << "ANALOG_DEVICES_GL847"; break;
|
||||
case FrontendType::WOLFSON_GL124: out << "WOLFSON_GL124"; break;
|
||||
default: out << "(unknown value)";
|
||||
}
|
||||
return out;
|
||||
|
@ -91,7 +96,7 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Frontend& frontend)
|
|||
StreamStateSaver state_saver{out};
|
||||
|
||||
out << "Genesys_Frontend{\n"
|
||||
<< " id: " << static_cast<unsigned>(frontend.id) << '\n'
|
||||
<< " id: " << frontend.id << '\n'
|
||||
<< " regs: " << format_indent_braced_list(4, frontend.regs) << '\n'
|
||||
<< std::hex
|
||||
<< " reg2[0]: " << frontend.reg2[0] << '\n'
|
||||
|
@ -112,33 +117,23 @@ std::ostream& operator<<(std::ostream& out, const SensorExposure& exposure)
|
|||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const ResolutionFilter& resolutions)
|
||||
{
|
||||
if (resolutions.matches_any()) {
|
||||
out << "ANY";
|
||||
return out;
|
||||
}
|
||||
out << format_vector_unsigned(4, resolutions.resolutions());
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const Genesys_Sensor& sensor)
|
||||
{
|
||||
out << "Genesys_Sensor{\n"
|
||||
<< " sensor_id: " << static_cast<unsigned>(sensor.sensor_id) << '\n'
|
||||
<< " optical_res: " << sensor.optical_res << '\n'
|
||||
<< " full_resolution: " << sensor.full_resolution << '\n'
|
||||
<< " optical_resolution: " << sensor.get_optical_resolution() << '\n'
|
||||
<< " resolutions: " << format_indent_braced_list(4, sensor.resolutions) << '\n'
|
||||
<< " channels: " << format_vector_unsigned(4, sensor.channels) << '\n'
|
||||
<< " method: " << sensor.method << '\n'
|
||||
<< " register_dpihw_override: " << sensor.register_dpihw_override << '\n'
|
||||
<< " logical_dpihw_override: " << sensor.logical_dpihw_override << '\n'
|
||||
<< " dpiset_override: " << sensor.dpiset_override << '\n'
|
||||
<< " ccd_size_divisor: " << sensor.ccd_size_divisor << '\n'
|
||||
<< " pixel_count_multiplier: " << sensor.pixel_count_multiplier << '\n'
|
||||
<< " register_dpihw: " << sensor.register_dpihw << '\n'
|
||||
<< " register_dpiset: " << sensor.register_dpiset << '\n'
|
||||
<< " shading_factor: " << sensor.shading_factor << '\n'
|
||||
<< " shading_pixel_offset: " << sensor.shading_pixel_offset << '\n'
|
||||
<< " pixel_count_ratio: " << sensor.pixel_count_ratio << '\n'
|
||||
<< " output_pixel_offset: " << sensor.output_pixel_offset << '\n'
|
||||
<< " black_pixels: " << sensor.black_pixels << '\n'
|
||||
<< " dummy_pixel: " << sensor.dummy_pixel << '\n'
|
||||
<< " ccd_start_xoffset: " << sensor.ccd_start_xoffset << '\n'
|
||||
<< " sensor_pixels: " << sensor.sensor_pixels << '\n'
|
||||
<< " fau_gain_white_ref: " << sensor.fau_gain_white_ref << '\n'
|
||||
<< " gain_white_ref: " << sensor.gain_white_ref << '\n'
|
||||
<< " exposure: " << format_indent_braced_list(4, sensor.exposure) << '\n'
|
||||
|
@ -147,7 +142,7 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Sensor& sensor)
|
|||
<< " segment_order: "
|
||||
<< format_indent_braced_list(4, format_vector_unsigned(4, sensor.segment_order)) << '\n'
|
||||
<< " stagger_config: " << format_indent_braced_list(4, sensor.stagger_config) << '\n'
|
||||
<< " custom_base_regs: " << format_indent_braced_list(4, sensor.custom_base_regs) << '\n'
|
||||
<< " use_host_side_calib: " << sensor.use_host_side_calib << '\n'
|
||||
<< " custom_regs: " << format_indent_braced_list(4, sensor.custom_regs) << '\n'
|
||||
<< " custom_fe_regs: " << format_indent_braced_list(4, sensor.custom_fe_regs) << '\n'
|
||||
<< " gamma.red: " << sensor.gamma[0] << '\n'
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "enums.h"
|
||||
#include "register.h"
|
||||
#include "serialize.h"
|
||||
#include "value_filter.h"
|
||||
#include <array>
|
||||
#include <functional>
|
||||
|
||||
|
@ -114,9 +115,14 @@ std::ostream& operator<<(std::ostream& out, const StaggerConfig& config);
|
|||
|
||||
enum class FrontendType : unsigned
|
||||
{
|
||||
UNKNOWN,
|
||||
UNKNOWN = 0,
|
||||
WOLFSON,
|
||||
ANALOG_DEVICES
|
||||
ANALOG_DEVICES,
|
||||
CANON_LIDE_80,
|
||||
WOLFSON_GL841, // old code path, likely wrong calculation
|
||||
WOLFSON_GL846, // old code path, likely wrong calculation
|
||||
ANALOG_DEVICES_GL847, // old code path, likely wrong calculation
|
||||
WOLFSON_GL124, // old code path, likely wrong calculation
|
||||
};
|
||||
|
||||
inline void serialize(std::istream& str, FrontendType& x)
|
||||
|
@ -242,54 +248,6 @@ struct SensorExposure {
|
|||
std::ostream& operator<<(std::ostream& out, const SensorExposure& exposure);
|
||||
|
||||
|
||||
class ResolutionFilter
|
||||
{
|
||||
public:
|
||||
struct Any {};
|
||||
static constexpr Any ANY{};
|
||||
|
||||
ResolutionFilter() : matches_any_{false} {}
|
||||
ResolutionFilter(Any) : matches_any_{true} {}
|
||||
ResolutionFilter(std::initializer_list<unsigned> resolutions) :
|
||||
matches_any_{false},
|
||||
resolutions_{resolutions}
|
||||
{}
|
||||
|
||||
bool matches(unsigned resolution) const
|
||||
{
|
||||
if (matches_any_)
|
||||
return true;
|
||||
auto it = std::find(resolutions_.begin(), resolutions_.end(), resolution);
|
||||
return it != resolutions_.end();
|
||||
}
|
||||
|
||||
bool operator==(const ResolutionFilter& other) const
|
||||
{
|
||||
return matches_any_ == other.matches_any_ && resolutions_ == other.resolutions_;
|
||||
}
|
||||
|
||||
bool matches_any() const { return matches_any_; }
|
||||
const std::vector<unsigned>& resolutions() const { return resolutions_; }
|
||||
|
||||
private:
|
||||
bool matches_any_ = false;
|
||||
std::vector<unsigned> resolutions_;
|
||||
|
||||
template<class Stream>
|
||||
friend void serialize(Stream& str, ResolutionFilter& x);
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const ResolutionFilter& resolutions);
|
||||
|
||||
template<class Stream>
|
||||
void serialize(Stream& str, ResolutionFilter& x)
|
||||
{
|
||||
serialize(str, x.matches_any_);
|
||||
serialize_newline(str);
|
||||
serialize(str, x.resolutions_);
|
||||
}
|
||||
|
||||
|
||||
struct Genesys_Sensor {
|
||||
|
||||
Genesys_Sensor() = default;
|
||||
|
@ -300,10 +258,15 @@ struct Genesys_Sensor {
|
|||
|
||||
// sensor resolution in CCD pixels. Note that we may read more than one CCD pixel per logical
|
||||
// pixel, see ccd_pixels_per_system_pixel()
|
||||
unsigned optical_res = 0;
|
||||
unsigned full_resolution = 0;
|
||||
|
||||
// sensor resolution in pixel values that are read by the chip. Many scanners make low
|
||||
// resolutions faster by configuring the timings in such a way that 1/2 or 1/4 of pixel values
|
||||
// that are read. If zero, then it is equal to `full_resolution`.
|
||||
unsigned optical_resolution = 0;
|
||||
|
||||
// the resolution list that the sensor is usable at.
|
||||
ResolutionFilter resolutions = ResolutionFilter::ANY;
|
||||
ValueFilterAny<unsigned> resolutions = VALUE_FILTER_ANY;
|
||||
|
||||
// the channel list that the sensor is usable at
|
||||
std::vector<unsigned> channels = { 1, 3 };
|
||||
|
@ -313,29 +276,31 @@ struct Genesys_Sensor {
|
|||
|
||||
// The scanner may be setup to use a custom dpihw that does not correspond to any actual
|
||||
// resolution. The value zero does not set the override.
|
||||
unsigned register_dpihw_override = 0;
|
||||
|
||||
// The scanner may be setup to use a custom logical dpihw that does not correspond to any actual
|
||||
// resolution. The value zero does not set the override.
|
||||
unsigned logical_dpihw_override = 0;
|
||||
unsigned register_dpihw = 0;
|
||||
|
||||
// The scanner may be setup to use a custom dpiset value that does not correspond to any actual
|
||||
// resolution. The value zero does not set the override.
|
||||
unsigned dpiset_override = 0;
|
||||
unsigned register_dpiset = 0;
|
||||
|
||||
// CCD may present itself as half or quarter-size CCD on certain resolutions
|
||||
int ccd_size_divisor = 1;
|
||||
// The resolution to use for shading calibration
|
||||
unsigned shading_resolution = 0;
|
||||
|
||||
// Some scanners need an additional multiplier over the scan coordinates
|
||||
int pixel_count_multiplier = 1;
|
||||
// How many real pixels correspond to one shading pixel that is sent to the scanner
|
||||
unsigned shading_factor = 1;
|
||||
|
||||
// How many pixels the shading data is offset from the acquired data
|
||||
int shading_pixel_offset = 0;
|
||||
|
||||
// This defines the ratio between logical pixel coordinates and the pixel coordinates sent to
|
||||
// the scanner.
|
||||
Ratio pixel_count_ratio = Ratio{1, 1};
|
||||
|
||||
// The offset in pixels in terms of scan resolution that needs to be applied to scan position.
|
||||
int output_pixel_offset = 0;
|
||||
|
||||
int black_pixels = 0;
|
||||
// value of the dummy register
|
||||
int dummy_pixel = 0;
|
||||
// last pixel of CCD margin at optical resolution
|
||||
int ccd_start_xoffset = 0;
|
||||
// total pixels used by the sensor
|
||||
int sensor_pixels = 0;
|
||||
// TA CCD target code (reference gain)
|
||||
int fau_gain_white_ref = 0;
|
||||
// CCD target code (reference gain)
|
||||
|
@ -359,27 +324,20 @@ struct Genesys_Sensor {
|
|||
// high-enough resolution, every other pixel column is shifted
|
||||
StaggerConfig stagger_config;
|
||||
|
||||
GenesysRegisterSettingSet custom_base_regs; // gl646-specific
|
||||
// True if calibration should be performed on host-side
|
||||
bool use_host_side_calib = false;
|
||||
|
||||
GenesysRegisterSettingSet custom_regs;
|
||||
GenesysRegisterSettingSet custom_fe_regs;
|
||||
|
||||
// red, green and blue gamma coefficient for default gamma tables
|
||||
AssignableArray<float, 3> gamma;
|
||||
|
||||
std::function<unsigned(const Genesys_Sensor&, unsigned)> get_logical_hwdpi_fun;
|
||||
std::function<unsigned(const Genesys_Sensor&, unsigned)> get_register_hwdpi_fun;
|
||||
std::function<unsigned(const Genesys_Sensor&, unsigned)> get_ccd_size_divisor_fun;
|
||||
std::function<unsigned(const Genesys_Sensor&, unsigned)> get_hwdpi_divisor_fun;
|
||||
|
||||
unsigned get_logical_hwdpi(unsigned xres) const { return get_logical_hwdpi_fun(*this, xres); }
|
||||
unsigned get_register_hwdpi(unsigned xres) const { return get_register_hwdpi_fun(*this, xres); }
|
||||
unsigned get_ccd_size_divisor_for_dpi(unsigned xres) const
|
||||
unsigned get_optical_resolution() const
|
||||
{
|
||||
return get_ccd_size_divisor_fun(*this, xres);
|
||||
}
|
||||
unsigned get_hwdpi_divisor_for_dpi(unsigned xres) const
|
||||
{
|
||||
return get_hwdpi_divisor_fun(*this, xres);
|
||||
if (optical_resolution != 0)
|
||||
return optical_resolution;
|
||||
return full_resolution;
|
||||
}
|
||||
|
||||
// how many CCD pixels are processed per system pixel time. This corresponds to CKSEL + 1
|
||||
|
@ -405,14 +363,17 @@ struct Genesys_Sensor {
|
|||
bool operator==(const Genesys_Sensor& other) const
|
||||
{
|
||||
return sensor_id == other.sensor_id &&
|
||||
optical_res == other.optical_res &&
|
||||
full_resolution == other.full_resolution &&
|
||||
optical_resolution == other.optical_resolution &&
|
||||
resolutions == other.resolutions &&
|
||||
method == other.method &&
|
||||
ccd_size_divisor == other.ccd_size_divisor &&
|
||||
shading_resolution == other.shading_resolution &&
|
||||
shading_factor == other.shading_factor &&
|
||||
shading_pixel_offset == other.shading_pixel_offset &&
|
||||
pixel_count_ratio == other.pixel_count_ratio &&
|
||||
output_pixel_offset == other.output_pixel_offset &&
|
||||
black_pixels == other.black_pixels &&
|
||||
dummy_pixel == other.dummy_pixel &&
|
||||
ccd_start_xoffset == other.ccd_start_xoffset &&
|
||||
sensor_pixels == other.sensor_pixels &&
|
||||
fau_gain_white_ref == other.fau_gain_white_ref &&
|
||||
gain_white_ref == other.gain_white_ref &&
|
||||
exposure == other.exposure &&
|
||||
|
@ -420,7 +381,7 @@ struct Genesys_Sensor {
|
|||
segment_size == other.segment_size &&
|
||||
segment_order == other.segment_order &&
|
||||
stagger_config == other.stagger_config &&
|
||||
custom_base_regs == other.custom_base_regs &&
|
||||
use_host_side_calib == other.use_host_side_calib &&
|
||||
custom_regs == other.custom_regs &&
|
||||
custom_fe_regs == other.custom_fe_regs &&
|
||||
gamma == other.gamma;
|
||||
|
@ -431,14 +392,16 @@ template<class Stream>
|
|||
void serialize(Stream& str, Genesys_Sensor& x)
|
||||
{
|
||||
serialize(str, x.sensor_id);
|
||||
serialize(str, x.optical_res);
|
||||
serialize(str, x.full_resolution);
|
||||
serialize(str, x.resolutions);
|
||||
serialize(str, x.method);
|
||||
serialize(str, x.ccd_size_divisor);
|
||||
serialize(str, x.shading_resolution);
|
||||
serialize(str, x.shading_factor);
|
||||
serialize(str, x.shading_pixel_offset);
|
||||
serialize(str, x.output_pixel_offset);
|
||||
serialize(str, x.pixel_count_ratio);
|
||||
serialize(str, x.black_pixels);
|
||||
serialize(str, x.dummy_pixel);
|
||||
serialize(str, x.ccd_start_xoffset);
|
||||
serialize(str, x.sensor_pixels);
|
||||
serialize(str, x.fau_gain_white_ref);
|
||||
serialize(str, x.gain_white_ref);
|
||||
serialize_newline(str);
|
||||
|
@ -453,7 +416,7 @@ void serialize(Stream& str, Genesys_Sensor& x)
|
|||
serialize_newline(str);
|
||||
serialize(str, x.stagger_config);
|
||||
serialize_newline(str);
|
||||
serialize(str, x.custom_base_regs);
|
||||
serialize(str, x.use_host_side_calib);
|
||||
serialize_newline(str);
|
||||
serialize(str, x.custom_regs);
|
||||
serialize_newline(str);
|
||||
|
|
|
@ -72,14 +72,20 @@ std::ostream& operator<<(std::ostream& out, const SetupParams& params)
|
|||
{
|
||||
StreamStateSaver state_saver{out};
|
||||
|
||||
bool reverse = has_flag(params.flags, ScanFlag::REVERSE);
|
||||
|
||||
out << "SetupParams{\n"
|
||||
<< " xres: " << params.xres << " yres: " << params.yres << '\n'
|
||||
<< " lines: " << params.lines << '\n'
|
||||
<< " pixels per line (actual): " << params.pixels << '\n'
|
||||
<< " pixels per line (requested): " << params.requested_pixels << '\n'
|
||||
<< " xres: " << params.xres
|
||||
<< " startx: " << params.startx
|
||||
<< " pixels per line (actual): " << params.pixels
|
||||
<< " pixels per line (requested): " << params.requested_pixels << '\n'
|
||||
|
||||
<< " yres: " << params.yres
|
||||
<< " lines: " << params.lines
|
||||
<< " starty: " << params.starty << (reverse ? " (reverse)" : "") << '\n'
|
||||
|
||||
<< " depth: " << params.depth << '\n'
|
||||
<< " channels: " << params.channels << '\n'
|
||||
<< " startx: " << params.startx << " starty: " << params.starty << '\n'
|
||||
<< " scan_mode: " << params.scan_mode << '\n'
|
||||
<< " color_filter: " << params.color_filter << '\n'
|
||||
<< " flags: " << params.flags << '\n'
|
||||
|
@ -87,16 +93,56 @@ std::ostream& operator<<(std::ostream& out, const SetupParams& params)
|
|||
return out;
|
||||
}
|
||||
|
||||
bool ScanSession::operator==(const ScanSession& other) const
|
||||
{
|
||||
return params == other.params &&
|
||||
computed == other.computed &&
|
||||
full_resolution == other.full_resolution &&
|
||||
optical_resolution == other.optical_resolution &&
|
||||
optical_pixels == other.optical_pixels &&
|
||||
optical_pixels_raw == other.optical_pixels_raw &&
|
||||
optical_line_count == other.optical_line_count &&
|
||||
output_resolution == other.output_resolution &&
|
||||
output_startx == other.output_startx &&
|
||||
output_pixels == other.output_pixels &&
|
||||
output_channel_bytes == other.output_channel_bytes &&
|
||||
output_line_bytes == other.output_line_bytes &&
|
||||
output_line_bytes_raw == other.output_line_bytes_raw &&
|
||||
output_line_bytes_requested == other.output_line_bytes_requested &&
|
||||
output_line_count == other.output_line_count &&
|
||||
output_total_bytes_raw == other.output_total_bytes_raw &&
|
||||
output_total_bytes == other.output_total_bytes &&
|
||||
num_staggered_lines == other.num_staggered_lines &&
|
||||
max_color_shift_lines == other.max_color_shift_lines &&
|
||||
color_shift_lines_r == other.color_shift_lines_r &&
|
||||
color_shift_lines_g == other.color_shift_lines_g &&
|
||||
color_shift_lines_b == other.color_shift_lines_b &&
|
||||
segment_count == other.segment_count &&
|
||||
pixel_startx == other.pixel_startx &&
|
||||
pixel_endx == other.pixel_endx &&
|
||||
pixel_count_ratio == other.pixel_count_ratio &&
|
||||
conseq_pixel_dist == other.conseq_pixel_dist &&
|
||||
output_segment_pixel_group_count == other.output_segment_pixel_group_count &&
|
||||
output_segment_start_offset == other.output_segment_start_offset &&
|
||||
buffer_size_read == other.buffer_size_read &&
|
||||
enable_ledadd == other.enable_ledadd &&
|
||||
use_host_side_calib == other.use_host_side_calib &&
|
||||
pipeline_needs_reorder == other.pipeline_needs_reorder &&
|
||||
pipeline_needs_ccd == other.pipeline_needs_ccd &&
|
||||
pipeline_needs_shrink == other.pipeline_needs_shrink;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const ScanSession& session)
|
||||
{
|
||||
out << "ScanSession{\n"
|
||||
<< " computed: " << session.computed << '\n'
|
||||
<< " hwdpi_divisor: " << session.hwdpi_divisor << '\n'
|
||||
<< " ccd_size_divisor: " << session.ccd_size_divisor << '\n'
|
||||
<< " full_resolution: " << session.full_resolution << '\n'
|
||||
<< " optical_resolution: " << session.optical_resolution << '\n'
|
||||
<< " optical_pixels: " << session.optical_pixels << '\n'
|
||||
<< " optical_pixels_raw: " << session.optical_pixels_raw << '\n'
|
||||
<< " optical_line_count: " << session.optical_line_count << '\n'
|
||||
<< " output_resolution: " << session.output_resolution << '\n'
|
||||
<< " output_startx: " << session.output_startx << '\n'
|
||||
<< " output_pixels: " << session.output_pixels << '\n'
|
||||
<< " output_line_bytes: " << session.output_line_bytes << '\n'
|
||||
<< " output_line_bytes_raw: " << session.output_line_bytes_raw << '\n'
|
||||
|
@ -110,13 +156,13 @@ std::ostream& operator<<(std::ostream& out, const ScanSession& session)
|
|||
<< " segment_count: " << session.segment_count << '\n'
|
||||
<< " pixel_startx: " << session.pixel_startx << '\n'
|
||||
<< " pixel_endx: " << session.pixel_endx << '\n'
|
||||
<< " pixel_count_ratio: " << session.pixel_count_ratio << '\n'
|
||||
<< " conseq_pixel_dist: " << session.conseq_pixel_dist << '\n'
|
||||
<< " output_segment_pixel_group_count: "
|
||||
<< session.output_segment_pixel_group_count << '\n'
|
||||
<< " buffer_size_read: " << session.buffer_size_read << '\n'
|
||||
<< " buffer_size_read: " << session.buffer_size_lines << '\n'
|
||||
<< " buffer_size_shrink: " << session.buffer_size_shrink << '\n'
|
||||
<< " buffer_size_out: " << session.buffer_size_out << '\n'
|
||||
<< " enable_ledadd: " << session.enable_ledadd << '\n'
|
||||
<< " use_host_side_calib: " << session.use_host_side_calib << '\n'
|
||||
<< " filters: "
|
||||
<< (session.pipeline_needs_reorder ? " reorder": "")
|
||||
<< (session.pipeline_needs_ccd ? " ccd": "")
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
|
||||
#include "enums.h"
|
||||
#include "serialize.h"
|
||||
#include "utilities.h"
|
||||
|
||||
namespace genesys {
|
||||
|
||||
|
@ -60,9 +61,9 @@ struct Genesys_Settings
|
|||
unsigned yres = 0;
|
||||
|
||||
//x start on scan table in mm
|
||||
double tl_x = 0;
|
||||
float tl_x = 0;
|
||||
// y start on scan table in mm
|
||||
double tl_y = 0;
|
||||
float tl_y = 0;
|
||||
|
||||
// number of lines at scan resolution
|
||||
unsigned int lines = 0;
|
||||
|
@ -116,12 +117,13 @@ struct SetupParams {
|
|||
unsigned xres = NOT_SET;
|
||||
// resolution in y direction
|
||||
unsigned yres = NOT_SET;
|
||||
// start pixel in X direction, from dummy_pixel + 1
|
||||
// start pixel in X direction, from dummy_pixel + 1. Counted in terms of xres.
|
||||
unsigned startx = NOT_SET;
|
||||
// start pixel in Y direction, counted according to base_ydpi
|
||||
unsigned starty = NOT_SET;
|
||||
// the number of pixels in X direction. Note that each logical pixel may correspond to more
|
||||
// than one CCD pixel, see CKSEL and GenesysSensor::ccd_pixels_per_system_pixel()
|
||||
// the number of pixels in X direction. Counted in terms of xres.
|
||||
// Note that each logical pixel may correspond to more than one CCD pixel, see CKSEL and
|
||||
// GenesysSensor::ccd_pixels_per_system_pixel()
|
||||
unsigned pixels = NOT_SET;
|
||||
|
||||
// the number of pixels in the X direction as requested by the frontend. This will be different
|
||||
|
@ -210,15 +212,10 @@ struct ScanSession {
|
|||
// whether the session setup has been computed via compute_session()
|
||||
bool computed = false;
|
||||
|
||||
// specifies the reduction (if any) of hardware dpi on the Genesys chip side.
|
||||
// except gl646
|
||||
unsigned hwdpi_divisor = 1;
|
||||
// specifies the full resolution of the sensor that is being used.
|
||||
unsigned full_resolution = 0;
|
||||
|
||||
// specifies the reduction (if any) of CCD effective dpi which is performed by latching the
|
||||
// data coming from CCD in such a way that 1/2 or 3/4 of pixel data is ignored.
|
||||
unsigned ccd_size_divisor = 1;
|
||||
|
||||
// the optical resolution of the scanner.
|
||||
// the optical resolution of the sensor that is being used.
|
||||
unsigned optical_resolution = 0;
|
||||
|
||||
// the number of pixels at the optical resolution, not including segmentation overhead.
|
||||
|
@ -228,10 +225,15 @@ struct ScanSession {
|
|||
// only on gl846, g847
|
||||
unsigned optical_pixels_raw = 0;
|
||||
|
||||
// the number of optical scan lines. Equal to output_line_count on CCD scanners.
|
||||
unsigned optical_line_count = 0;
|
||||
|
||||
// the resolution of the output data.
|
||||
// gl843-only
|
||||
unsigned output_resolution = 0;
|
||||
|
||||
// the offset in pixels from the beginning of output data
|
||||
unsigned output_startx = 0;
|
||||
|
||||
// the number of pixels in output data (after desegmentation)
|
||||
unsigned output_pixels = 0;
|
||||
|
||||
|
@ -280,8 +282,18 @@ struct ScanSession {
|
|||
unsigned pixel_startx = 0;
|
||||
unsigned pixel_endx = 0;
|
||||
|
||||
// certain scanners require the logical pixel count to be multiplied on certain resolutions
|
||||
unsigned pixel_count_multiplier = 1;
|
||||
/* The following defines the ratio between logical pixel count and pixel count setting sent to
|
||||
the scanner. The ratio is affected by the following:
|
||||
|
||||
- Certain scanners just like to multiply the pixel number by a multiplier that depends on
|
||||
the resolution.
|
||||
|
||||
- The sensor may be configured to output one value per multiple physical pixels
|
||||
|
||||
- The scanner will automatically average the pixels that come from the sensor using a
|
||||
certain ratio.
|
||||
*/
|
||||
Ratio pixel_count_ratio = Ratio{1, 1};
|
||||
|
||||
// Distance in pixels between consecutive pixels, e.g. between odd and even pixels. Note that
|
||||
// the number of segments can be large.
|
||||
|
@ -297,15 +309,15 @@ struct ScanSession {
|
|||
// Currently it's always zero.
|
||||
unsigned output_segment_start_offset = 0;
|
||||
|
||||
// the sizes of the corresponding buffers
|
||||
// the size of the read buffer.
|
||||
size_t buffer_size_read = 0;
|
||||
size_t buffer_size_lines = 0;
|
||||
size_t buffer_size_shrink = 0;
|
||||
size_t buffer_size_out = 0;
|
||||
|
||||
// whether to enable ledadd functionality
|
||||
bool enable_ledadd = false;
|
||||
|
||||
// whether calibration should be performed host-side
|
||||
bool use_host_side_calib = false;
|
||||
|
||||
// what pipeline modifications are needed
|
||||
bool pipeline_needs_reorder = false;
|
||||
bool pipeline_needs_ccd = false;
|
||||
|
@ -317,10 +329,53 @@ struct ScanSession {
|
|||
throw std::runtime_error("ScanSession is not computed");
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const ScanSession& other) const;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const ScanSession& session);
|
||||
|
||||
template<class Stream>
|
||||
void serialize(Stream& str, ScanSession& x)
|
||||
{
|
||||
serialize(str, x.params);
|
||||
serialize_newline(str);
|
||||
serialize(str, x.computed);
|
||||
serialize(str, x.full_resolution);
|
||||
serialize(str, x.optical_resolution);
|
||||
serialize(str, x.optical_pixels);
|
||||
serialize(str, x.optical_pixels_raw);
|
||||
serialize(str, x.optical_line_count);
|
||||
serialize(str, x.output_resolution);
|
||||
serialize(str, x.output_startx);
|
||||
serialize(str, x.output_pixels);
|
||||
serialize(str, x.output_channel_bytes);
|
||||
serialize(str, x.output_line_bytes);
|
||||
serialize(str, x.output_line_bytes_raw);
|
||||
serialize(str, x.output_line_bytes_requested);
|
||||
serialize(str, x.output_line_count);
|
||||
serialize(str, x.output_total_bytes_raw);
|
||||
serialize(str, x.output_total_bytes);
|
||||
serialize(str, x.num_staggered_lines);
|
||||
serialize(str, x.max_color_shift_lines);
|
||||
serialize(str, x.color_shift_lines_r);
|
||||
serialize(str, x.color_shift_lines_g);
|
||||
serialize(str, x.color_shift_lines_b);
|
||||
serialize(str, x.segment_count);
|
||||
serialize(str, x.pixel_startx);
|
||||
serialize(str, x.pixel_endx);
|
||||
serialize(str, x.pixel_count_ratio);
|
||||
serialize(str, x.conseq_pixel_dist);
|
||||
serialize(str, x.output_segment_pixel_group_count);
|
||||
serialize(str, x.output_segment_start_offset);
|
||||
serialize(str, x.buffer_size_read);
|
||||
serialize(str, x.enable_ledadd);
|
||||
serialize(str, x.use_host_side_calib);
|
||||
serialize(str, x.pipeline_needs_reorder);
|
||||
serialize(str, x.pipeline_needs_ccd);
|
||||
serialize(str, x.pipeline_needs_shrink);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const SANE_Parameters& params);
|
||||
|
||||
} // namespace genesys
|
||||
|
|
|
@ -60,7 +60,8 @@ void genesys_init_frontend_tables()
|
|||
|
||||
GenesysFrontendLayout analog_devices;
|
||||
analog_devices.type = FrontendType::ANALOG_DEVICES;
|
||||
|
||||
analog_devices.offset_addr = { 0x05, 0x06, 0x07 };
|
||||
analog_devices.gain_addr = { 0x02, 0x03, 0x04 };
|
||||
|
||||
Genesys_Frontend fe;
|
||||
fe.id = AdcId::WOLFSON_UMAX;
|
||||
|
@ -198,6 +199,7 @@ void genesys_init_frontend_tables()
|
|||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::CANON_LIDE_35;
|
||||
fe.layout = wolfson_layout;
|
||||
fe.layout.type = FrontendType::WOLFSON_GL841;
|
||||
fe.regs = {
|
||||
{ 0x00, 0x00 },
|
||||
{ 0x01, 0x3d },
|
||||
|
@ -242,6 +244,7 @@ void genesys_init_frontend_tables()
|
|||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::WOLFSON_XP300;
|
||||
fe.layout = wolfson_layout;
|
||||
fe.layout.type = FrontendType::WOLFSON_GL841;
|
||||
fe.regs = {
|
||||
{ 0x00, 0x00 },
|
||||
{ 0x01, 0x35 },
|
||||
|
@ -286,6 +289,7 @@ void genesys_init_frontend_tables()
|
|||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::WOLFSON_DSM600;
|
||||
fe.layout = wolfson_layout;
|
||||
fe.layout.type = FrontendType::WOLFSON_GL841;
|
||||
fe.regs = {
|
||||
{ 0x00, 0x00 },
|
||||
{ 0x01, 0x35 },
|
||||
|
@ -307,45 +311,35 @@ void genesys_init_frontend_tables()
|
|||
|
||||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::CANON_LIDE_200;
|
||||
fe.layout = wolfson_layout;
|
||||
fe.layout = analog_devices;
|
||||
fe.layout.type = FrontendType::ANALOG_DEVICES_GL847;
|
||||
fe.regs = {
|
||||
{ 0x00, 0x9d },
|
||||
{ 0x01, 0x91 },
|
||||
{ 0x02, 0x00 },
|
||||
{ 0x03, 0x00 },
|
||||
{ 0x20, 0x00 },
|
||||
{ 0x21, 0x3f },
|
||||
{ 0x22, 0x00 },
|
||||
{ 0x24, 0x00 },
|
||||
{ 0x25, 0x00 },
|
||||
{ 0x26, 0x00 },
|
||||
{ 0x28, 0x32 },
|
||||
{ 0x29, 0x04 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x02, 0x32 },
|
||||
{ 0x03, 0x04 },
|
||||
{ 0x04, 0x00 },
|
||||
{ 0x05, 0x00 },
|
||||
{ 0x06, 0x3f },
|
||||
{ 0x07, 0x00 },
|
||||
};
|
||||
fe.reg2 = {0x00, 0x00, 0x00};
|
||||
s_frontends->push_back(fe);
|
||||
|
||||
|
||||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::CANON_LIDE_700F;
|
||||
fe.layout = wolfson_layout;
|
||||
fe.layout = analog_devices;
|
||||
fe.layout.type = FrontendType::ANALOG_DEVICES_GL847;
|
||||
fe.regs = {
|
||||
{ 0x00, 0x9d },
|
||||
{ 0x01, 0x9e },
|
||||
{ 0x02, 0x00 },
|
||||
{ 0x03, 0x00 },
|
||||
{ 0x20, 0x00 },
|
||||
{ 0x21, 0x3f },
|
||||
{ 0x22, 0x00 },
|
||||
{ 0x24, 0x00 },
|
||||
{ 0x25, 0x00 },
|
||||
{ 0x26, 0x00 },
|
||||
{ 0x28, 0x2f },
|
||||
{ 0x29, 0x04 },
|
||||
{ 0x2a, 0x00 },
|
||||
{ 0x02, 0x2f },
|
||||
{ 0x03, 0x04 },
|
||||
{ 0x04, 0x00 },
|
||||
{ 0x05, 0x00 },
|
||||
{ 0x06, 0x3f },
|
||||
{ 0x07, 0x00 },
|
||||
};
|
||||
fe.reg2 = {0x00, 0x00, 0x00};
|
||||
s_frontends->push_back(fe);
|
||||
|
||||
|
||||
|
@ -396,6 +390,7 @@ void genesys_init_frontend_tables()
|
|||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::CANON_LIDE_110;
|
||||
fe.layout = wolfson_layout;
|
||||
fe.layout.type = FrontendType::WOLFSON_GL124;
|
||||
fe.regs = {
|
||||
{ 0x00, 0x80 },
|
||||
{ 0x01, 0x8a },
|
||||
|
@ -422,6 +417,7 @@ void genesys_init_frontend_tables()
|
|||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::CANON_LIDE_120;
|
||||
fe.layout = wolfson_layout;
|
||||
fe.layout.type = FrontendType::WOLFSON_GL124;
|
||||
fe.regs = {
|
||||
{ 0x00, 0x80 },
|
||||
{ 0x01, 0xa3 },
|
||||
|
@ -463,6 +459,23 @@ void genesys_init_frontend_tables()
|
|||
s_frontends->push_back(fe);
|
||||
|
||||
|
||||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::PLUSTEK_OPTICFILM_7200;
|
||||
fe.layout = analog_devices;
|
||||
fe.regs = {
|
||||
{ 0x00, 0xf8 },
|
||||
{ 0x01, 0x80 },
|
||||
{ 0x02, 0x2e },
|
||||
{ 0x03, 0x17 },
|
||||
{ 0x04, 0x20 },
|
||||
{ 0x05, 0x0109 },
|
||||
{ 0x06, 0x01 },
|
||||
{ 0x07, 0x0104 },
|
||||
};
|
||||
fe.reg2 = {0x00, 0x00, 0x00};
|
||||
s_frontends->push_back(fe);
|
||||
|
||||
|
||||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::PLUSTEK_OPTICFILM_7200I;
|
||||
fe.layout = analog_devices;
|
||||
|
@ -497,6 +510,23 @@ void genesys_init_frontend_tables()
|
|||
s_frontends->push_back(fe);
|
||||
|
||||
|
||||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::PLUSTEK_OPTICFILM_7400;
|
||||
fe.layout = analog_devices;
|
||||
fe.regs = {
|
||||
{ 0x00, 0xf8 },
|
||||
{ 0x01, 0x80 },
|
||||
{ 0x02, 0x1f },
|
||||
{ 0x03, 0x14 },
|
||||
{ 0x04, 0x19 },
|
||||
{ 0x05, 0x1b },
|
||||
{ 0x06, 0x1e },
|
||||
{ 0x07, 0x0e },
|
||||
};
|
||||
fe.reg2 = {0x00, 0x00, 0x00};
|
||||
s_frontends->push_back(fe);
|
||||
|
||||
|
||||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::PLUSTEK_OPTICFILM_7500I;
|
||||
fe.layout = analog_devices;
|
||||
|
@ -514,6 +544,23 @@ void genesys_init_frontend_tables()
|
|||
s_frontends->push_back(fe);
|
||||
|
||||
|
||||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::PLUSTEK_OPTICFILM_8200I;
|
||||
fe.layout = analog_devices;
|
||||
fe.regs = {
|
||||
{ 0x00, 0xf8 },
|
||||
{ 0x01, 0x80 },
|
||||
{ 0x02, 0x28 },
|
||||
{ 0x03, 0x20 },
|
||||
{ 0x04, 0x28 },
|
||||
{ 0x05, 0x2f },
|
||||
{ 0x06, 0x2d },
|
||||
{ 0x07, 0x23 },
|
||||
};
|
||||
fe.reg2 = {0x00, 0x00, 0x00};
|
||||
s_frontends->push_back(fe);
|
||||
|
||||
|
||||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::CANON_4400F;
|
||||
fe.layout = wolfson_layout;
|
||||
|
@ -583,6 +630,7 @@ void genesys_init_frontend_tables()
|
|||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::IMG101;
|
||||
fe.layout = wolfson_layout;
|
||||
fe.layout.type = FrontendType::WOLFSON_GL846;
|
||||
fe.regs = {
|
||||
{ 0x00, 0x78 },
|
||||
{ 0x01, 0xf0 },
|
||||
|
@ -605,6 +653,7 @@ void genesys_init_frontend_tables()
|
|||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::PLUSTEK_OPTICBOOK_3800;
|
||||
fe.layout = wolfson_layout;
|
||||
fe.layout.type = FrontendType::WOLFSON_GL846;
|
||||
fe.regs = {
|
||||
{ 0x00, 0x78 },
|
||||
{ 0x01, 0xf0 },
|
||||
|
@ -631,6 +680,7 @@ void genesys_init_frontend_tables()
|
|||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::CANON_LIDE_80;
|
||||
fe.layout = wolfson_layout;
|
||||
fe.layout.type = FrontendType::CANON_LIDE_80;
|
||||
fe.regs = {
|
||||
{ 0x00, 0x70 },
|
||||
{ 0x01, 0x16 },
|
||||
|
|
|
@ -188,10 +188,15 @@ void genesys_init_gpo_tables()
|
|||
gpo = Genesys_Gpo();
|
||||
gpo.id = GpioId::CANON_LIDE_200;
|
||||
gpo.regs = {
|
||||
{ 0x6c, 0xfb }, // 0xfb when idle , 0xf9/0xe9 (1200) when scanning
|
||||
{ 0x6b, 0x02 },
|
||||
{ 0x6c, 0xf9 }, // 0xfb when idle , 0xf9/0xe9 (1200) when scanning
|
||||
{ 0x6d, 0x20 },
|
||||
{ 0x6e, 0xff },
|
||||
{ 0x6f, 0x00 },
|
||||
{ 0xa6, 0x04 },
|
||||
{ 0xa7, 0x04 },
|
||||
{ 0xa8, 0x00 },
|
||||
{ 0xa9, 0x00 },
|
||||
};
|
||||
s_gpo->push_back(gpo);
|
||||
|
||||
|
@ -199,10 +204,15 @@ void genesys_init_gpo_tables()
|
|||
gpo = Genesys_Gpo();
|
||||
gpo.id = GpioId::CANON_LIDE_700F;
|
||||
gpo.regs = {
|
||||
{ 0x6b, 0x06 },
|
||||
{ 0x6c, 0xdb },
|
||||
{ 0x6d, 0xff },
|
||||
{ 0x6e, 0xff },
|
||||
{ 0x6f, 0x80 },
|
||||
{ 0xa6, 0x15 },
|
||||
{ 0xa7, 0x07 },
|
||||
{ 0xa8, 0x20 },
|
||||
{ 0xa9, 0x10 },
|
||||
};
|
||||
s_gpo->push_back(gpo);
|
||||
|
||||
|
@ -292,6 +302,19 @@ void genesys_init_gpo_tables()
|
|||
s_gpo->push_back(gpo);
|
||||
|
||||
|
||||
gpo = Genesys_Gpo();
|
||||
gpo.id = GpioId::PLUSTEK_OPTICFILM_7200;
|
||||
gpo.regs = {
|
||||
{ 0x6b, 0x33 },
|
||||
{ 0x6c, 0x00 },
|
||||
{ 0x6d, 0x80 },
|
||||
{ 0x6e, 0x0c },
|
||||
{ 0x6f, 0x80 },
|
||||
{ 0x7e, 0x00 }
|
||||
};
|
||||
s_gpo->push_back(gpo);
|
||||
|
||||
|
||||
gpo = Genesys_Gpo();
|
||||
gpo.id = GpioId::PLUSTEK_OPTICFILM_7200I;
|
||||
gpo.regs = {
|
||||
|
@ -320,6 +343,16 @@ void genesys_init_gpo_tables()
|
|||
};
|
||||
s_gpo->push_back(gpo);
|
||||
|
||||
|
||||
gpo = Genesys_Gpo();
|
||||
gpo.id = GpioId::PLUSTEK_OPTICFILM_7400;
|
||||
gpo.regs = {
|
||||
{ 0x6b, 0x30 }, { 0x6c, 0x4c }, { 0x6d, 0x80 }, { 0x6e, 0x4c }, { 0x6f, 0x80 },
|
||||
{ 0xa6, 0x00 }, { 0xa7, 0x07 }, { 0xa8, 0x20 }, { 0xa9, 0x01 },
|
||||
};
|
||||
s_gpo->push_back(gpo);
|
||||
|
||||
|
||||
gpo = Genesys_Gpo();
|
||||
gpo.id = GpioId::PLUSTEK_OPTICFILM_7500I;
|
||||
gpo.regs = {
|
||||
|
@ -334,6 +367,16 @@ void genesys_init_gpo_tables()
|
|||
};
|
||||
s_gpo->push_back(gpo);
|
||||
|
||||
|
||||
gpo = Genesys_Gpo();
|
||||
gpo.id = GpioId::PLUSTEK_OPTICFILM_8200I;
|
||||
gpo.regs = {
|
||||
{ 0x6b, 0x30 }, { 0x6c, 0x4c }, { 0x6d, 0x80 }, { 0x6e, 0x4c }, { 0x6f, 0x80 },
|
||||
{ 0xa6, 0x00 }, { 0xa7, 0x07 }, { 0xa8, 0x20 }, { 0xa9, 0x01 },
|
||||
};
|
||||
s_gpo->push_back(gpo);
|
||||
|
||||
|
||||
gpo = Genesys_Gpo();
|
||||
gpo.id = GpioId::CANON_4400F;
|
||||
gpo.regs = {
|
||||
|
@ -382,10 +425,8 @@ void genesys_init_gpo_tables()
|
|||
gpo = Genesys_Gpo();
|
||||
gpo.id = GpioId::IMG101;
|
||||
gpo.regs = {
|
||||
{ 0x6c, 0x41 },
|
||||
{ 0x6d, 0xa4 },
|
||||
{ 0x6e, 0x13 },
|
||||
{ 0x6f, 0xa7 },
|
||||
{ 0x6b, 0x72 }, { 0x6c, 0x1f }, { 0x6d, 0xa4 }, { 0x6e, 0x13 }, { 0x6f, 0xa7 },
|
||||
{ 0xa6, 0x11 }, { 0xa7, 0xff }, { 0xa8, 0x19 }, { 0xa9, 0x05 },
|
||||
};
|
||||
s_gpo->push_back(gpo);
|
||||
|
||||
|
@ -393,10 +434,8 @@ void genesys_init_gpo_tables()
|
|||
gpo = Genesys_Gpo();
|
||||
gpo.id = GpioId::PLUSTEK_OPTICBOOK_3800;
|
||||
gpo.regs = {
|
||||
{ 0x6c, 0x41 },
|
||||
{ 0x6d, 0xa4 },
|
||||
{ 0x6e, 0x13 },
|
||||
{ 0x6f, 0xa7 },
|
||||
{ 0x6b, 0x30 }, { 0x6c, 0x01 }, { 0x6d, 0x80 }, { 0x6e, 0x2d }, { 0x6f, 0x80 },
|
||||
{ 0xa6, 0x0c }, { 0xa7, 0x8f }, { 0xa8, 0x08 }, { 0xa9, 0x04 },
|
||||
};
|
||||
s_gpo->push_back(gpo);
|
||||
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2020 Povilas Kanapickas <povilas@radix.lt>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
|
||||
#include "low.h"
|
||||
|
||||
namespace genesys {
|
||||
|
||||
StaticInit<std::vector<MemoryLayout>> s_memory_layout;
|
||||
|
||||
void genesys_init_memory_layout_tables()
|
||||
{
|
||||
s_memory_layout.init();
|
||||
|
||||
MemoryLayout ml;
|
||||
ml.models = { ModelId::CANON_IMAGE_FORMULA_101 };
|
||||
// FIXME: this scanner does not set all required registers
|
||||
ml.regs = {
|
||||
{ 0xe0, 0x00 }, { 0xe1, 0xb0 }, { 0xe2, 0x05 }, { 0xe3, 0xe7 },
|
||||
{ 0xe4, 0x05 }, { 0xe5, 0xe8 }, { 0xe6, 0x0b }, { 0xe7, 0x1f },
|
||||
{ 0xe8, 0x0b }, { 0xe9, 0x20 },
|
||||
};
|
||||
s_memory_layout->push_back(ml);
|
||||
|
||||
|
||||
ml = MemoryLayout();
|
||||
ml.models = { ModelId::PLUSTEK_OPTICBOOK_3800 };
|
||||
// FIXME: this scanner does not set all required registers
|
||||
ml.regs = {
|
||||
{ 0xe0, 0x00 }, { 0xe1, 0x68 }, { 0xe2, 0x03 }, { 0xe3, 0x00 },
|
||||
{ 0xe4, 0x03 }, { 0xe5, 0x01 }, { 0xe6, 0x05 }, { 0xe7, 0x99 },
|
||||
{ 0xe8, 0x05 }, { 0xe9, 0x9a },
|
||||
};
|
||||
s_memory_layout->push_back(ml);
|
||||
|
||||
ml = MemoryLayout();
|
||||
ml.models = { ModelId::PLUSTEK_OPTICFILM_7400, ModelId::PLUSTEK_OPTICFILM_8200I };
|
||||
ml.regs = {
|
||||
{ 0x81, 0x6d }, { 0x82, 0x00 }, { 0x83, 0x00 }, { 0x84, 0x00 },
|
||||
{ 0x85, 0x00 }, { 0x86, 0x00 },
|
||||
{ 0xd0, 0x0a }, { 0xd1, 0x0a }, { 0xd2, 0x0a },
|
||||
{ 0xe0, 0x00 }, { 0xe1, 0x68 }, { 0xe2, 0x03 }, { 0xe3, 0x00 },
|
||||
{ 0xe4, 0x03 }, { 0xe5, 0x01 }, { 0xe6, 0x05 }, { 0xe7, 0x99 },
|
||||
{ 0xe8, 0x05 }, { 0xe9, 0x9a }, { 0xea, 0x08 }, { 0xeb, 0x32 },
|
||||
{ 0xec, 0x08 }, { 0xed, 0x33 }, { 0xee, 0x0a }, { 0xef, 0xcb },
|
||||
{ 0xf0, 0x0a }, { 0xf1, 0xcc }, { 0xf2, 0x0d }, { 0xf3, 0x64 },
|
||||
{ 0xf4, 0x0d }, { 0xf5, 0x65 }, { 0xf6, 0x0f }, { 0xf7, 0xfd },
|
||||
};
|
||||
s_memory_layout->push_back(ml);
|
||||
|
||||
|
||||
/* On GL847 and GL124, the values of the base address for shading data must be multiplied by
|
||||
8192=0x4000 to give address on AHB
|
||||
|
||||
On GL847 and GL124, the values of the base address for scanned data must be multiplied by
|
||||
1024*2=0x0800 to give address on AHB
|
||||
*/
|
||||
ml = MemoryLayout();
|
||||
ml.models = { ModelId::CANON_LIDE_100 };
|
||||
ml.regs = {
|
||||
{ 0xd0, 0x0a }, { 0xd1, 0x15 }, { 0xd2, 0x20 },
|
||||
{ 0xe0, 0x00 }, { 0xe1, 0xac }, { 0xe2, 0x02 }, { 0xe3, 0x55 },
|
||||
{ 0xe4, 0x02 }, { 0xe5, 0x56 }, { 0xe6, 0x03 }, { 0xe7, 0xff },
|
||||
{ 0xe8, 0x00 }, { 0xe9, 0xac }, { 0xea, 0x02 }, { 0xeb, 0x55 },
|
||||
{ 0xec, 0x02 }, { 0xed, 0x56 }, { 0xee, 0x03 }, { 0xef, 0xff },
|
||||
{ 0xf0, 0x00 }, { 0xf1, 0xac }, { 0xf2, 0x02 }, { 0xf3, 0x55 },
|
||||
{ 0xf4, 0x02 }, { 0xf5, 0x56 }, { 0xf6, 0x03 }, { 0xf7, 0xff },
|
||||
};
|
||||
s_memory_layout->push_back(ml);
|
||||
|
||||
|
||||
ml = MemoryLayout();
|
||||
// BUG: we shouldn't use LIDE_200 data for 5600F
|
||||
ml.models = { ModelId::CANON_LIDE_200, ModelId::CANON_5600F };
|
||||
ml.regs = {
|
||||
{ 0xd0, 0x0a }, { 0xd1, 0x1f }, { 0xd2, 0x34 },
|
||||
{ 0xe0, 0x01 }, { 0xe1, 0x24 }, { 0xe2, 0x02 }, { 0xe3, 0x91 },
|
||||
{ 0xe4, 0x02 }, { 0xe5, 0x92 }, { 0xe6, 0x03 }, { 0xe7, 0xff },
|
||||
{ 0xe8, 0x01 }, { 0xe9, 0x24 }, { 0xea, 0x02 }, { 0xeb, 0x91 },
|
||||
{ 0xec, 0x02 }, { 0xed, 0x92 }, { 0xee, 0x03 }, { 0xef, 0xff },
|
||||
{ 0xf0, 0x01 }, { 0xf1, 0x24 }, { 0xf2, 0x02 }, { 0xf3, 0x91 },
|
||||
{ 0xf4, 0x02 }, { 0xf5, 0x92 }, { 0xf6, 0x03 }, { 0xf7, 0xff },
|
||||
};
|
||||
s_memory_layout->push_back(ml);
|
||||
|
||||
|
||||
ml = MemoryLayout();
|
||||
ml.models = { ModelId::CANON_LIDE_700F };
|
||||
ml.regs = {
|
||||
{ 0xd0, 0x0a }, { 0xd1, 0x33 }, { 0xd2, 0x5c },
|
||||
{ 0xe0, 0x02 }, { 0xe1, 0x14 }, { 0xe2, 0x09 }, { 0xe3, 0x09 },
|
||||
{ 0xe4, 0x09 }, { 0xe5, 0x0a }, { 0xe6, 0x0f }, { 0xe7, 0xff },
|
||||
{ 0xe8, 0x02 }, { 0xe9, 0x14 }, { 0xea, 0x09 }, { 0xeb, 0x09 },
|
||||
{ 0xec, 0x09 }, { 0xed, 0x0a }, { 0xee, 0x0f }, { 0xef, 0xff },
|
||||
{ 0xf0, 0x02 }, { 0xf1, 0x14 }, { 0xf2, 0x09 }, { 0xf3, 0x09 },
|
||||
{ 0xf4, 0x09 }, { 0xf5, 0x0a }, { 0xf6, 0x0f }, { 0xf7, 0xff },
|
||||
};
|
||||
s_memory_layout->push_back(ml);
|
||||
|
||||
|
||||
ml = MemoryLayout();
|
||||
ml.models = { ModelId::CANON_LIDE_110, ModelId::CANON_LIDE_120 };
|
||||
ml.regs = {
|
||||
{ 0xd0, 0x0a }, { 0xd1, 0x15 }, { 0xd2, 0x20 },
|
||||
{ 0xe0, 0x00 }, { 0xe1, 0xac }, { 0xe2, 0x08 }, { 0xe3, 0x55 },
|
||||
{ 0xe4, 0x08 }, { 0xe5, 0x56 }, { 0xe6, 0x0f }, { 0xe7, 0xff },
|
||||
{ 0xe8, 0x00 }, { 0xe9, 0xac }, { 0xea, 0x08 }, { 0xeb, 0x55 },
|
||||
{ 0xec, 0x08 }, { 0xed, 0x56 }, { 0xee, 0x0f }, { 0xef, 0xff },
|
||||
{ 0xf0, 0x00 }, { 0xf1, 0xac }, { 0xf2, 0x08 }, { 0xf3, 0x55 },
|
||||
{ 0xf4, 0x08 }, { 0xf5, 0x56 }, { 0xf6, 0x0f }, { 0xf7, 0xff },
|
||||
|
||||
};
|
||||
s_memory_layout->push_back(ml);
|
||||
|
||||
|
||||
ml = MemoryLayout();
|
||||
ml.models = { ModelId::CANON_LIDE_210, ModelId::CANON_LIDE_220 };
|
||||
ml.regs = {
|
||||
{ 0xd0, 0x0a }, { 0xd1, 0x1f }, { 0xd2, 0x34 },
|
||||
{ 0xe0, 0x01 }, { 0xe1, 0x24 }, { 0xe2, 0x08 }, { 0xe3, 0x91 },
|
||||
{ 0xe4, 0x08 }, { 0xe5, 0x92 }, { 0xe6, 0x0f }, { 0xe7, 0xff },
|
||||
{ 0xe8, 0x01 }, { 0xe9, 0x24 }, { 0xea, 0x08 }, { 0xeb, 0x91 },
|
||||
{ 0xec, 0x08 }, { 0xed, 0x92 }, { 0xee, 0x0f }, { 0xef, 0xff },
|
||||
{ 0xf0, 0x01 }, { 0xf1, 0x24 }, { 0xf2, 0x08 }, { 0xf3, 0x91 },
|
||||
{ 0xf4, 0x08 }, { 0xf5, 0x92 }, { 0xf6, 0x0f }, { 0xf7, 0xff },
|
||||
};
|
||||
s_memory_layout->push_back(ml);
|
||||
}
|
||||
|
||||
} // namespace genesys
|
Plik diff jest za duży
Load Diff
|
@ -53,272 +53,541 @@ void genesys_init_motor_tables()
|
|||
{
|
||||
s_motors.init();
|
||||
|
||||
MotorProfile profile;
|
||||
|
||||
Genesys_Motor motor;
|
||||
motor.id = MotorId::UMAX;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 2400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
|
||||
motor.base_ydpi = 2400;
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(11000, 3000, 128), StepType::FULL, 0});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(11000, 3000, 128), StepType::HALF, 0});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::MD_5345; // MD5345/6228/6471
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 2400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(2000, 1375, 128));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(2000, 1375, 128));
|
||||
motor.base_ydpi = 2400;
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(2000, 1375, 128), StepType::FULL, 0});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(2000, 1375, 128), StepType::HALF, 0});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::ST24;
|
||||
motor.base_ydpi = 2400;
|
||||
motor.optical_ydpi = 2400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(2289, 2100, 128));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(2289, 2100, 128));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(2289, 2100, 128), StepType::FULL, 0});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(2289, 2100, 128), StepType::HALF, 0});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::HP3670;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 1200;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(11000, 3000, 128), StepType::FULL, 0});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(11000, 3000, 128), StepType::HALF, 0});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::HP2400;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 1200;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(11000, 3000, 128), StepType::FULL, 0});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(11000, 3000, 128), StepType::HALF, 0});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::HP2300;
|
||||
motor.base_ydpi = 600;
|
||||
motor.optical_ydpi = 1200;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3200, 1200, 128));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3200, 1200, 128));
|
||||
motor.base_ydpi = 1200;
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(3200, 1200, 128), StepType::FULL, 0});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(3200, 1200, 128), StepType::HALF, 0});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_LIDE_35;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 2400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1400, 60));
|
||||
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(3500, 1300, 150), StepType::HALF, 0};
|
||||
profile.resolutions = { 75, 150, 200, 300, 600 };
|
||||
motor.profiles.push_back(profile);
|
||||
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(3500, 1300, 150), StepType::QUARTER, 0};
|
||||
profile.resolutions = { 1200, 2400 };
|
||||
motor.profiles.push_back(profile);
|
||||
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(3500, 1400, 150), StepType::FULL, 0};
|
||||
profile.resolutions = { 75, 150, 200, 300 };
|
||||
motor.fast_profiles.push_back(profile);
|
||||
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(6000, 3000, 100), StepType::FULL, 0};
|
||||
profile.resolutions = { 600, 1200, 2400 };
|
||||
motor.fast_profiles.push_back(profile);
|
||||
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_LIDE_60;
|
||||
motor.base_ydpi = 1200;
|
||||
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(3500, 1400, 150), StepType::HALF, 0};
|
||||
motor.profiles.push_back(profile);
|
||||
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(3500, 1400, 150), StepType::FULL, 0};
|
||||
profile.resolutions = { 75, 150, 300 };
|
||||
motor.fast_profiles.push_back(profile);
|
||||
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(6000, 3000, 100), StepType::FULL, 0};
|
||||
profile.resolutions = { 600, 1200, 2400 };
|
||||
motor.fast_profiles.push_back(profile);
|
||||
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::XP200;
|
||||
motor.base_ydpi = 600;
|
||||
motor.optical_ydpi = 600;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(3500, 1300, 60), StepType::FULL, 0});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(3500, 1300, 60), StepType::HALF, 0});
|
||||
motor.fast_profiles.push_back({MotorSlope::create_from_steps(3500, 1300, 60), StepType::FULL, 0});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::XP300;
|
||||
motor.base_ydpi = 300;
|
||||
motor.optical_ydpi = 600;
|
||||
// works best with GPIO10, GPIO14 off
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3700, 3700, 2));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 11000, 2));
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(3700, 3700, 2), StepType::FULL, 0};
|
||||
profile.resolutions = {}; // used during fast moves
|
||||
motor.profiles.push_back(profile);
|
||||
|
||||
// FIXME: this motor profile is useless
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(11000, 11000, 2), StepType::HALF, 0};
|
||||
profile.resolutions = {75, 150, 300, 600};
|
||||
motor.profiles.push_back(profile);
|
||||
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(3700, 3700, 2), StepType::FULL, 0};
|
||||
motor.fast_profiles.push_back(profile);
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::DP665;
|
||||
motor.base_ydpi = 750;
|
||||
motor.optical_ydpi = 1500;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 2500, 10));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 11000, 2));
|
||||
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(3000, 2500, 10), StepType::FULL, 0};
|
||||
profile.resolutions = {75, 150};
|
||||
motor.profiles.push_back(profile);
|
||||
|
||||
// FIXME: this motor profile is useless
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(11000, 11000, 2), StepType::HALF, 0};
|
||||
profile.resolutions = {300, 600, 1200};
|
||||
motor.profiles.push_back(profile);
|
||||
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(3000, 2500, 10), StepType::FULL, 0};
|
||||
motor.fast_profiles.push_back(profile);
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::ROADWARRIOR;
|
||||
motor.base_ydpi = 750;
|
||||
motor.optical_ydpi = 1500;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 2600, 10));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 11000, 2));
|
||||
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(3000, 2600, 10), StepType::FULL, 0};
|
||||
profile.resolutions = {75, 150};
|
||||
motor.profiles.push_back(profile);
|
||||
|
||||
// FIXME: this motor profile is useless
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(11000, 11000, 2), StepType::HALF, 0};
|
||||
profile.resolutions = {300, 600, 1200};
|
||||
motor.profiles.push_back(profile);
|
||||
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(3000, 2600, 10), StepType::FULL, 0};
|
||||
motor.fast_profiles.push_back(profile);
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::DSMOBILE_600;
|
||||
motor.base_ydpi = 750;
|
||||
motor.optical_ydpi = 1500;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(6666, 3700, 8));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(6666, 3700, 8));
|
||||
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(6666, 3700, 8), StepType::FULL, 0};
|
||||
profile.resolutions = {75, 150};
|
||||
motor.profiles.push_back(profile);
|
||||
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(6666, 3700, 8), StepType::HALF, 0};
|
||||
profile.resolutions = {300, 600, 1200};
|
||||
motor.profiles.push_back(profile);
|
||||
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(6666, 3700, 8), StepType::FULL, 0};
|
||||
motor.fast_profiles.push_back(profile);
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_LIDE_100;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 6400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 127));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1500, 127));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3 * 2712, 3 * 2712, 16));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 864, 255),
|
||||
StepType::HALF, 1432});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 864, 279),
|
||||
StepType::QUARTER, 2712});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(31680, 864, 247),
|
||||
StepType::EIGHTH, 5280});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_LIDE_200;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 6400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 127));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1500, 127));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3 * 2712, 3 * 2712, 16));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 864, 255),
|
||||
StepType::HALF, 1432});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 864, 279),
|
||||
StepType::QUARTER, 2712});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(31680, 864, 247),
|
||||
StepType::EIGHTH, 5280});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(31680, 864, 247),
|
||||
StepType::EIGHTH, 10416});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_LIDE_700;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 6400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 127));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1500, 127));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3 * 2712, 3 * 2712, 16));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 534, 255),
|
||||
StepType::HALF, 1424});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 534, 255),
|
||||
StepType::HALF, 1504});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 2022, 127),
|
||||
StepType::HALF, 2696});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 534, 255),
|
||||
StepType::HALF, 2848});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 15864, 2),
|
||||
StepType::EIGHTH, 10576});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::KVSS080;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 1200;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(22222, 500, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(22222, 500, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(22222, 500, 246));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(44444, 500, 489),
|
||||
StepType::HALF, 8000});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::G4050;
|
||||
motor.base_ydpi = 2400;
|
||||
motor.optical_ydpi = 9600;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(7842, 320, 602),
|
||||
StepType::HALF, 8016});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(9422, 254, 1004),
|
||||
StepType::HALF, 15624});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(28032, 2238, 604),
|
||||
StepType::HALF, 56064});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(42752, 1706, 610),
|
||||
StepType::QUARTER, 42752});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_4400F;
|
||||
motor.base_ydpi = 2400;
|
||||
motor.optical_ydpi = 9600;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(28597 * 2, 727 * 2, 200);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 1;
|
||||
profile.resolutions = { 300, 600 };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(28597 * 2, 727 * 2, 200);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 0;
|
||||
profile.resolutions = { 1200, 2400, 4800, 9600 };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(28597 * 2, 279 * 2, 1000);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 0;
|
||||
motor.fast_profiles.push_back(std::move(profile));
|
||||
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_8400F;
|
||||
motor.base_ydpi = 1600;
|
||||
motor.optical_ydpi = 6400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(20202 * 4, 333 * 4, 100);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 0;
|
||||
profile.resolutions = VALUE_FILTER_ANY;
|
||||
profile.scan_methods = { ScanMethod::FLATBED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(65535 * 4, 333 * 4, 100);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 2;
|
||||
profile.resolutions = VALUE_FILTER_ANY;
|
||||
profile.scan_methods = { ScanMethod::TRANSPARENCY, ScanMethod::TRANSPARENCY_INFRARED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(65535 * 4, 333 * 4, 200);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 2;
|
||||
profile.resolutions = VALUE_FILTER_ANY;
|
||||
profile.scan_methods = VALUE_FILTER_ANY;
|
||||
motor.fast_profiles.push_back(std::move(profile));
|
||||
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_8600F;
|
||||
motor.base_ydpi = 2400;
|
||||
motor.optical_ydpi = 9600;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 3;
|
||||
profile.resolutions = { 300, 600 };
|
||||
profile.scan_methods = { ScanMethod::FLATBED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 2;
|
||||
profile.resolutions = { 1200, 2400 };
|
||||
profile.scan_methods = { ScanMethod::FLATBED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 2;
|
||||
profile.resolutions = { 4800 };
|
||||
profile.scan_methods = { ScanMethod::FLATBED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 2;
|
||||
profile.resolutions = { 300, 600 };
|
||||
profile.scan_methods = { ScanMethod::TRANSPARENCY,
|
||||
ScanMethod::TRANSPARENCY_INFRARED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 1;
|
||||
profile.resolutions = { 1200, 2400 };
|
||||
profile.scan_methods = { ScanMethod::TRANSPARENCY,
|
||||
ScanMethod::TRANSPARENCY_INFRARED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 0;
|
||||
profile.resolutions = { 4800 };
|
||||
profile.scan_methods = { ScanMethod::TRANSPARENCY,
|
||||
ScanMethod::TRANSPARENCY_INFRARED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(59240, 582, 1020);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 2;
|
||||
motor.fast_profiles.push_back(std::move(profile));
|
||||
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_LIDE_110;
|
||||
motor.base_ydpi = 4800;
|
||||
motor.optical_ydpi = 9600;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 256));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 335, 255),
|
||||
StepType::FULL, 2768});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 335, 469),
|
||||
StepType::HALF, 5360});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 2632, 3),
|
||||
StepType::HALF, 10528});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 10432, 3),
|
||||
StepType::QUARTER, 20864});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_LIDE_120;
|
||||
motor.base_ydpi = 4800;
|
||||
motor.optical_ydpi = 9600;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 256));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 864, 127),
|
||||
StepType::FULL, 4608});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 2010, 63),
|
||||
StepType::HALF, 5360});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62464, 2632, 3),
|
||||
StepType::QUARTER, 10528});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62592, 10432, 5),
|
||||
StepType::QUARTER, 20864});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_LIDE_210;
|
||||
motor.base_ydpi = 4800;
|
||||
motor.optical_ydpi = 9600;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 256));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 335, 255),
|
||||
StepType::FULL, 2768});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 335, 469),
|
||||
StepType::HALF, 5360});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 2632, 3),
|
||||
StepType::HALF, 10528});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 10432, 4),
|
||||
StepType::QUARTER, 20864});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 10432, 4),
|
||||
StepType::EIGHTH, 41536});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::PLUSTEK_OPTICPRO_3600;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 2400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 3250, 60));
|
||||
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(3500, 1300, 60), StepType::FULL, 0};
|
||||
profile.resolutions = {75, 100, 150, 200};
|
||||
motor.profiles.push_back(profile);
|
||||
|
||||
// FIXME: this motor profile is almost useless
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(3500, 3250, 60), StepType::HALF, 0};
|
||||
profile.resolutions = {300, 400, 600, 1200};
|
||||
motor.profiles.push_back(profile);
|
||||
|
||||
profile = MotorProfile{MotorSlope::create_from_steps(3500, 1300, 60), StepType::FULL, 0};
|
||||
motor.fast_profiles.push_back(profile);
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::PLUSTEK_OPTICFILM_7200;
|
||||
motor.base_ydpi = 3600;
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(20000 * 2, 600 * 2, 200);
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.motor_vref = 0;
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::PLUSTEK_OPTICFILM_7200I;
|
||||
motor.base_ydpi = 3600;
|
||||
motor.optical_ydpi = 3600;
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(34722 * 2, 454 * 2, 40);
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.motor_vref = 3;
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(34722 * 2, 454 * 2, 40);
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.motor_vref = 0;
|
||||
motor.fast_profiles.push_back(std::move(profile));
|
||||
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::PLUSTEK_OPTICFILM_7300;
|
||||
motor.base_ydpi = 3600;
|
||||
motor.optical_ydpi = 3600;
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(56818 * 4, 454 * 4, 30);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 3;
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(56818 * 4, 454 * 4, 30);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 0;
|
||||
motor.fast_profiles.push_back(std::move(profile));
|
||||
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::PLUSTEK_OPTICFILM_7400;
|
||||
motor.base_ydpi = 3600;
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(64102 * 4, 400 * 4, 30);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 3;
|
||||
motor.profiles.push_back(profile);
|
||||
motor.fast_profiles.push_back(profile);
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::PLUSTEK_OPTICFILM_7500I;
|
||||
motor.base_ydpi = 3600;
|
||||
motor.optical_ydpi = 3600;
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(56818 * 4, 454 * 4, 30);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 3;
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(56818 * 4, 454 * 4, 30);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 0;
|
||||
motor.fast_profiles.push_back(std::move(profile));
|
||||
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::PLUSTEK_OPTICFILM_8200I;
|
||||
motor.base_ydpi = 3600;
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(64102 * 4, 400 * 4, 100);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 3;
|
||||
motor.profiles.push_back(profile);
|
||||
motor.fast_profiles.push_back(profile);
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::IMG101;
|
||||
motor.base_ydpi = 600;
|
||||
motor.optical_ydpi = 1200;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 3250, 60));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(22000, 1000, 1017),
|
||||
StepType::HALF, 11000});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::PLUSTEK_OPTICBOOK_3800;
|
||||
motor.base_ydpi = 600;
|
||||
motor.optical_ydpi = 1200;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 3250, 60));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(22000, 1000, 1017),
|
||||
StepType::HALF, 11000});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_LIDE_80;
|
||||
motor.base_ydpi = 2400;
|
||||
motor.optical_ydpi = 4800; // 9600
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(9560, 1912, 31));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(9560, 1912, 31), StepType::FULL, 0});
|
||||
s_motors->push_back(std::move(motor));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,380 +0,0 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
|
||||
#include "low.h"
|
||||
|
||||
namespace genesys {
|
||||
|
||||
StaticInit<std::vector<Motor_Profile>> gl843_motor_profiles;
|
||||
|
||||
void genesys_init_motor_profile_tables_gl843()
|
||||
{
|
||||
gl843_motor_profiles.init();
|
||||
|
||||
auto profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::KVSS080;
|
||||
profile.exposure = 8000;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(44444, 500, 489);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::G4050;
|
||||
profile.exposure = 8016;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(7842, 320, 602);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::G4050;
|
||||
profile.exposure = 15624;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(9422, 254, 1004);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::G4050;
|
||||
profile.exposure = 42752;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(42752, 1706, 610);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::G4050;
|
||||
profile.exposure = 56064;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(28032, 2238, 604);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_4400F;
|
||||
profile.exposure = 11640;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(49152, 484, 1014);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_8400F;
|
||||
profile.exposure = 50000;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(8743, 300, 794);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_8600F;
|
||||
profile.exposure = 0x59d8;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
// FIXME: if the exposure is lower then we'll select another motor
|
||||
profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::PLUSTEK_OPTICFILM_7200I;
|
||||
profile.exposure = 0;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(39682, 1191, 15);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::PLUSTEK_OPTICFILM_7300;
|
||||
profile.exposure = 0x2f44;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(31250, 1512, 6);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::PLUSTEK_OPTICFILM_7500I;
|
||||
profile.exposure = 0;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(31250, 1375, 7);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
}
|
||||
|
||||
StaticInit<std::vector<Motor_Profile>> gl846_motor_profiles;
|
||||
|
||||
void genesys_init_motor_profile_tables_gl846()
|
||||
{
|
||||
gl846_motor_profiles.init();
|
||||
|
||||
auto profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::IMG101;
|
||||
profile.exposure = 11000;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(22000, 1000, 1017);
|
||||
|
||||
gl846_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::PLUSTEK_OPTICBOOK_3800;
|
||||
profile.exposure = 11000;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(22000, 1000, 1017);
|
||||
gl846_motor_profiles->push_back(profile);
|
||||
}
|
||||
|
||||
/**
|
||||
* database of motor profiles
|
||||
*/
|
||||
|
||||
StaticInit<std::vector<Motor_Profile>> gl847_motor_profiles;
|
||||
|
||||
void genesys_init_motor_profile_tables_gl847()
|
||||
{
|
||||
gl847_motor_profiles.init();
|
||||
|
||||
auto profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_100;
|
||||
profile.exposure = 2848;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_100;
|
||||
profile.exposure = 1424;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_100;
|
||||
profile.exposure = 1432;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_100;
|
||||
profile.exposure = 2712;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 279);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_100;
|
||||
profile.exposure = 5280;
|
||||
profile.step_type = StepType::EIGHTH;
|
||||
profile.slope = MotorSlope::create_from_steps(31680, 534, 247);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_200;
|
||||
profile.exposure = 2848;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_200;
|
||||
profile.exposure = 1424;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_200;
|
||||
profile.exposure = 1432;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_200;
|
||||
profile.exposure = 2712;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 279);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_200;
|
||||
profile.exposure = 5280;
|
||||
profile.step_type = StepType::EIGHTH;
|
||||
profile.slope = MotorSlope::create_from_steps(31680, 534, 247);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_200;
|
||||
profile.exposure = 10416;
|
||||
profile.step_type = StepType::EIGHTH;
|
||||
profile.slope = MotorSlope::create_from_steps(31680, 534, 247);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_700;
|
||||
profile.exposure = 2848;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_700;
|
||||
profile.exposure = 1424;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_700;
|
||||
profile.exposure = 1504;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_700;
|
||||
profile.exposure = 2696;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 2022, 127);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_700;
|
||||
profile.exposure = 10576;
|
||||
profile.step_type = StepType::EIGHTH;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 15864, 2);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
}
|
||||
|
||||
StaticInit<std::vector<Motor_Profile>> gl124_motor_profiles;
|
||||
|
||||
void genesys_init_motor_profile_tables_gl124()
|
||||
{
|
||||
gl124_motor_profiles.init();
|
||||
|
||||
// NEXT LPERIOD=PREVIOUS*2-192
|
||||
Motor_Profile profile;
|
||||
profile.motor_id = MotorId::CANON_LIDE_110;
|
||||
profile.exposure = 2768;
|
||||
profile.step_type = StepType::FULL;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 335, 255);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_110;
|
||||
profile.exposure = 5360;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 335, 469);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_110;
|
||||
profile.exposure = 10528;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 2632, 3);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_110;
|
||||
profile.exposure = 20864;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 10432, 3);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_120;
|
||||
profile.exposure = 4608;
|
||||
profile.step_type = StepType::FULL;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 864, 127);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_120;
|
||||
profile.exposure = 5360;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 2010, 63);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_120;
|
||||
profile.exposure = 10528;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(62464, 2632, 3);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_120;
|
||||
profile.exposure = 20864;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(62592, 10432, 5);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_210;
|
||||
profile.exposure = 2768;
|
||||
profile.step_type = StepType::FULL;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 335, 255);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_210;
|
||||
profile.exposure = 5360;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 335, 469);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_210;
|
||||
profile.exposure = 10528;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 2632, 3);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_210;
|
||||
profile.exposure = 20864;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 10432, 4);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
}
|
||||
|
||||
void genesys_init_motor_profile_tables()
|
||||
{
|
||||
genesys_init_motor_profile_tables_gl843();
|
||||
genesys_init_motor_profile_tables_gl846();
|
||||
genesys_init_motor_profile_tables_gl847();
|
||||
genesys_init_motor_profile_tables_gl124();
|
||||
}
|
||||
|
||||
} // namespace genesys
|
Plik diff jest za duży
Load Diff
|
@ -49,7 +49,10 @@
|
|||
|
||||
namespace genesys {
|
||||
|
||||
TestScannerInterface::TestScannerInterface(Genesys_Device* dev) : dev_{dev}
|
||||
TestScannerInterface::TestScannerInterface(Genesys_Device* dev, uint16_t vendor_id,
|
||||
uint16_t product_id, uint16_t bcd_device) :
|
||||
dev_{dev},
|
||||
usb_dev_{vendor_id, product_id, bcd_device}
|
||||
{
|
||||
// initialize status registers
|
||||
if (dev_->model->asic_type == AsicType::GL124) {
|
||||
|
@ -58,6 +61,7 @@ TestScannerInterface::TestScannerInterface(Genesys_Device* dev) : dev_{dev}
|
|||
write_register(0x41, 0x00);
|
||||
}
|
||||
if (dev_->model->asic_type == AsicType::GL841 ||
|
||||
dev_->model->asic_type == AsicType::GL842 ||
|
||||
dev_->model->asic_type == AsicType::GL843 ||
|
||||
dev_->model->asic_type == AsicType::GL845 ||
|
||||
dev_->model->asic_type == AsicType::GL846 ||
|
||||
|
@ -137,23 +141,21 @@ void TestScannerInterface::bulk_write_data(std::uint8_t addr, std::uint8_t* data
|
|||
}
|
||||
|
||||
void TestScannerInterface::write_buffer(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags)
|
||||
std::size_t size)
|
||||
{
|
||||
(void) type;
|
||||
(void) addr;
|
||||
(void) data;
|
||||
(void) size;
|
||||
(void) flags;
|
||||
}
|
||||
|
||||
void TestScannerInterface::write_gamma(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags)
|
||||
std::size_t size)
|
||||
{
|
||||
(void) type;
|
||||
(void) addr;
|
||||
(void) data;
|
||||
(void) size;
|
||||
(void) flags;
|
||||
}
|
||||
|
||||
void TestScannerInterface::write_ahb(std::uint32_t addr, std::uint32_t size, std::uint8_t* data)
|
||||
|
|
|
@ -56,7 +56,8 @@ namespace genesys {
|
|||
class TestScannerInterface : public ScannerInterface
|
||||
{
|
||||
public:
|
||||
TestScannerInterface(Genesys_Device* dev);
|
||||
TestScannerInterface(Genesys_Device* dev, std::uint16_t vendor_id, std::uint16_t product_id,
|
||||
std::uint16_t bcd_device);
|
||||
|
||||
~TestScannerInterface() override;
|
||||
|
||||
|
@ -74,9 +75,9 @@ public:
|
|||
void bulk_write_data(std::uint8_t addr, std::uint8_t* data, std::size_t size) override;
|
||||
|
||||
void write_buffer(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags) override;
|
||||
std::size_t size) override;
|
||||
void write_gamma(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags) override;
|
||||
std::size_t size) override;
|
||||
void write_ahb(std::uint32_t addr, std::uint32_t size, std::uint8_t* data) override;
|
||||
|
||||
std::uint16_t read_fe_register(std::uint8_t address) override;
|
||||
|
|
|
@ -52,6 +52,7 @@ namespace {
|
|||
bool s_testing_mode = false;
|
||||
std::uint16_t s_vendor_id = 0;
|
||||
std::uint16_t s_product_id = 0;
|
||||
std::uint16_t s_bcd_device = 0;
|
||||
TestCheckpointCallback s_checkpoint_callback;
|
||||
|
||||
} // namespace
|
||||
|
@ -66,15 +67,17 @@ void disable_testing_mode()
|
|||
s_testing_mode = false;
|
||||
s_vendor_id = 0;
|
||||
s_product_id = 0;
|
||||
|
||||
s_bcd_device = 0;
|
||||
}
|
||||
|
||||
void enable_testing_mode(std::uint16_t vendor_id, std::uint16_t product_id,
|
||||
std::uint16_t bcd_device,
|
||||
TestCheckpointCallback checkpoint_callback)
|
||||
{
|
||||
s_testing_mode = true;
|
||||
s_vendor_id = vendor_id;
|
||||
s_product_id = product_id;
|
||||
s_bcd_device = bcd_device;
|
||||
s_checkpoint_callback = checkpoint_callback;
|
||||
}
|
||||
|
||||
|
@ -88,6 +91,11 @@ std::uint16_t get_testing_product_id()
|
|||
return s_product_id;
|
||||
}
|
||||
|
||||
std::uint16_t get_testing_bcd_device()
|
||||
{
|
||||
return s_bcd_device;
|
||||
}
|
||||
|
||||
std::string get_testing_device_name()
|
||||
{
|
||||
std::string name;
|
||||
|
|
|
@ -58,9 +58,11 @@ using TestCheckpointCallback = std::function<void(const Genesys_Device&,
|
|||
bool is_testing_mode();
|
||||
void disable_testing_mode();
|
||||
void enable_testing_mode(std::uint16_t vendor_id, std::uint16_t product_id,
|
||||
std::uint16_t bcd_device,
|
||||
TestCheckpointCallback checkpoint_callback);
|
||||
std::uint16_t get_testing_vendor_id();
|
||||
std::uint16_t get_testing_product_id();
|
||||
std::uint16_t get_testing_bcd_device();
|
||||
std::string get_testing_device_name();
|
||||
TestCheckpointCallback get_testing_checkpoint_callback();
|
||||
|
||||
|
|
|
@ -48,9 +48,11 @@
|
|||
|
||||
namespace genesys {
|
||||
|
||||
TestUsbDevice::TestUsbDevice(std::uint16_t vendor, std::uint16_t product) :
|
||||
TestUsbDevice::TestUsbDevice(std::uint16_t vendor, std::uint16_t product,
|
||||
std::uint16_t bcd_device) :
|
||||
vendor_{vendor},
|
||||
product_{product}
|
||||
product_{product},
|
||||
bcd_device_{bcd_device}
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -94,12 +96,25 @@ void TestUsbDevice::close()
|
|||
name_ = "";
|
||||
}
|
||||
|
||||
void TestUsbDevice::get_vendor_product(int& vendor, int& product)
|
||||
std::uint16_t TestUsbDevice::get_vendor_id()
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
assert_is_open();
|
||||
vendor = vendor_;
|
||||
product = product_;
|
||||
return vendor_;
|
||||
}
|
||||
|
||||
std::uint16_t TestUsbDevice::get_product_id()
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
assert_is_open();
|
||||
return product_;
|
||||
}
|
||||
|
||||
std::uint16_t TestUsbDevice::get_bcd_device()
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
assert_is_open();
|
||||
return bcd_device_;
|
||||
}
|
||||
|
||||
void TestUsbDevice::control_msg(int rtype, int reg, int value, int index, int length,
|
||||
|
|
|
@ -50,9 +50,7 @@ namespace genesys {
|
|||
|
||||
class TestUsbDevice : public IUsbDevice {
|
||||
public:
|
||||
TestUsbDevice(std::uint16_t vendor, std::uint16_t product);
|
||||
TestUsbDevice() = default;
|
||||
|
||||
TestUsbDevice(std::uint16_t vendor, std::uint16_t product, std::uint16_t bcd_device);
|
||||
~TestUsbDevice() override;
|
||||
|
||||
bool is_open() const override { return is_open_; }
|
||||
|
@ -65,7 +63,9 @@ public:
|
|||
void reset() override;
|
||||
void close() override;
|
||||
|
||||
void get_vendor_product(int& vendor, int& product) override;
|
||||
std::uint16_t get_vendor_id() override;
|
||||
std::uint16_t get_product_id() override;
|
||||
std::uint16_t get_bcd_device() override;
|
||||
|
||||
void control_msg(int rtype, int reg, int value, int index, int length,
|
||||
std::uint8_t* data) override;
|
||||
|
@ -78,6 +78,7 @@ private:
|
|||
bool is_open_ = false;
|
||||
std::uint16_t vendor_ = 0;
|
||||
std::uint16_t product_ = 0;
|
||||
std::uint16_t bcd_device_ = 0;
|
||||
};
|
||||
|
||||
} // namespace genesys
|
||||
|
|
|
@ -101,11 +101,33 @@ void UsbDevice::close()
|
|||
sanei_usb_close(device_num);
|
||||
}
|
||||
|
||||
void UsbDevice::get_vendor_product(int& vendor, int& product)
|
||||
std::uint16_t UsbDevice::get_vendor_id()
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
assert_is_open();
|
||||
int vendor = 0;
|
||||
int product = 0;
|
||||
TIE(sanei_usb_get_vendor_product(device_num_, &vendor, &product));
|
||||
return static_cast<std::uint16_t>(vendor);
|
||||
}
|
||||
|
||||
std::uint16_t UsbDevice::get_product_id()
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
assert_is_open();
|
||||
int vendor = 0;
|
||||
int product = 0;
|
||||
TIE(sanei_usb_get_vendor_product(device_num_, &vendor, &product));
|
||||
return static_cast<std::uint16_t>(product);
|
||||
}
|
||||
|
||||
std::uint16_t UsbDevice::get_bcd_device()
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
assert_is_open();
|
||||
sanei_usb_dev_descriptor desc;
|
||||
TIE(sanei_usb_get_descriptor(device_num_, &desc));
|
||||
return desc.bcd_dev;
|
||||
}
|
||||
|
||||
void UsbDevice::control_msg(int rtype, int reg, int value, int index, int length,
|
||||
|
|
|
@ -71,7 +71,9 @@ public:
|
|||
virtual void reset() = 0;
|
||||
virtual void close() = 0;
|
||||
|
||||
virtual void get_vendor_product(int& vendor, int& product) = 0;
|
||||
virtual std::uint16_t get_vendor_id() = 0;
|
||||
virtual std::uint16_t get_product_id() = 0;
|
||||
virtual std::uint16_t get_bcd_device() = 0;
|
||||
|
||||
virtual void control_msg(int rtype, int reg, int value, int index, int length,
|
||||
std::uint8_t* data) = 0;
|
||||
|
@ -96,7 +98,9 @@ public:
|
|||
void reset() override;
|
||||
void close() override;
|
||||
|
||||
void get_vendor_product(int& vendor, int& product) override;
|
||||
std::uint16_t get_vendor_id() override;
|
||||
std::uint16_t get_product_id() override;
|
||||
std::uint16_t get_bcd_device() override;
|
||||
|
||||
void control_msg(int rtype, int reg, int value, int index, int length,
|
||||
std::uint8_t* data) override;
|
||||
|
|
|
@ -46,12 +46,36 @@
|
|||
|
||||
#include "error.h"
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace genesys {
|
||||
|
||||
// just like SANE_FIX and SANE_UNFIX except that the conversion is done by a function and argument
|
||||
// precision is handled correctly
|
||||
inline SANE_Word double_to_fixed(double v)
|
||||
{
|
||||
return static_cast<SANE_Word>(v * (1 << SANE_FIXED_SCALE_SHIFT));
|
||||
}
|
||||
|
||||
inline SANE_Word float_to_fixed(float v)
|
||||
{
|
||||
return static_cast<SANE_Word>(v * (1 << SANE_FIXED_SCALE_SHIFT));
|
||||
}
|
||||
|
||||
inline float fixed_to_float(SANE_Word v)
|
||||
{
|
||||
return static_cast<float>(v) / (1 << SANE_FIXED_SCALE_SHIFT);
|
||||
}
|
||||
|
||||
inline double fixed_to_double(SANE_Word v)
|
||||
{
|
||||
return static_cast<double>(v) / (1 << SANE_FIXED_SCALE_SHIFT);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void compute_array_percentile_approx(T* result, const T* data,
|
||||
std::size_t line_count, std::size_t elements_per_line,
|
||||
|
@ -85,6 +109,75 @@ void compute_array_percentile_approx(T* result, const T* data,
|
|||
}
|
||||
}
|
||||
|
||||
class Ratio
|
||||
{
|
||||
public:
|
||||
Ratio() : multiplier_{1}, divisor_{1}
|
||||
{
|
||||
}
|
||||
|
||||
Ratio(unsigned multiplier, unsigned divisor) : multiplier_{multiplier}, divisor_{divisor}
|
||||
{
|
||||
}
|
||||
|
||||
unsigned multiplier() const { return multiplier_; }
|
||||
unsigned divisor() const { return divisor_; }
|
||||
|
||||
unsigned apply(unsigned arg) const
|
||||
{
|
||||
return static_cast<std::uint64_t>(arg) * multiplier_ / divisor_;
|
||||
}
|
||||
|
||||
int apply(int arg) const
|
||||
{
|
||||
return static_cast<std::int64_t>(arg) * multiplier_ / divisor_;
|
||||
}
|
||||
|
||||
float apply(float arg) const
|
||||
{
|
||||
return arg * multiplier_ / divisor_;
|
||||
}
|
||||
|
||||
unsigned apply_inverse(unsigned arg) const
|
||||
{
|
||||
return static_cast<std::uint64_t>(arg) * divisor_ / multiplier_;
|
||||
}
|
||||
|
||||
int apply_inverse(int arg) const
|
||||
{
|
||||
return static_cast<std::int64_t>(arg) * divisor_ / multiplier_;
|
||||
}
|
||||
|
||||
float apply_inverse(float arg) const
|
||||
{
|
||||
return arg * divisor_ / multiplier_;
|
||||
}
|
||||
|
||||
bool operator==(const Ratio& other) const
|
||||
{
|
||||
return multiplier_ == other.multiplier_ && divisor_ == other.divisor_;
|
||||
}
|
||||
private:
|
||||
unsigned multiplier_;
|
||||
unsigned divisor_;
|
||||
|
||||
template<class Stream>
|
||||
friend void serialize(Stream& str, Ratio& x);
|
||||
};
|
||||
|
||||
template<class Stream>
|
||||
void serialize(Stream& str, Ratio& x)
|
||||
{
|
||||
serialize(str, x.multiplier_);
|
||||
serialize(str, x.divisor_);
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const Ratio& ratio)
|
||||
{
|
||||
out << ratio.multiplier() << "/" << ratio.divisor();
|
||||
return out;
|
||||
}
|
||||
|
||||
template<class Char, class Traits>
|
||||
class BasicStreamStateSaver
|
||||
{
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Ładowanie…
Reference in New Issue