kopia lustrzana https://gitlab.com/sane-project/backends
Merge branch 'master' into 159-canon-mf113w-not-working
# Conflicts solved: # backend/pixma/pixma.hmerge-requests/244/head
commit
fe118fda01
|
@ -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 --with-poppler-glib"
|
||||
CONFIGURE_FULL: "--with-usb --with-usb-record-replay --with-avahi --enable-pnm-backend --with-libcurl --with-poppler-glib"
|
||||
|
||||
stages:
|
||||
- tarball
|
||||
|
@ -76,18 +76,25 @@ 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
|
||||
|
||||
alpine-3.11-musl:
|
||||
image: $REGISTRY_HUB:alpine-3.11-musl
|
||||
alpine-3.12-musl:
|
||||
image: $REGISTRY_HUB:alpine-3.12-musl
|
||||
variables:
|
||||
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
|
||||
|
|
1
AUTHORS
1
AUTHORS
|
@ -13,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
|
||||
|
|
|
@ -25,6 +25,7 @@ $ make install
|
|||
- 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:
|
||||
|
|
33
NEWS
33
NEWS
|
@ -2,6 +2,10 @@
|
|||
|
||||
## New with the next release
|
||||
|
||||
### Backends
|
||||
|
||||
- adds an `canon_lide70` backend
|
||||
|
||||
### Documentation
|
||||
|
||||
- removes the SANE Standard. This is now maintained as a separate
|
||||
|
@ -11,6 +15,35 @@
|
|||
### 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.
|
||||
|
||||
### Backends
|
||||
|
||||
- `epson2`: fixes CVE-2020-12867 (GHSL-2020-075) and several memory
|
||||
management issues found while addressing that CVE
|
||||
- `epsonds`: addresses out-of-bound memory access issues to fix
|
||||
CVE-2020-12862 (GHSL-2020-082) and CVE-2020-12863 (GHSL-2020-083),
|
||||
addresses a buffer overflow fixing CVE-2020-12865 (GHSL-2020-084)
|
||||
and disables network autodiscovery to mitigate CVE-2020-12866
|
||||
(GHSL-2020-079), CVE-2020-12861 (GHSL-2020-080) and CVE-2020-12864
|
||||
(GHSL-2020-081). Note that this backend does not support network
|
||||
scanners to begin with.
|
||||
- `magicolor`: fixes a floating point exception and uninitialized data
|
||||
read
|
||||
- fixes an overflow in `sanei_tcp_read()`
|
||||
|
||||
### Build
|
||||
|
||||
- fixes a build issue where linker flags would become link time
|
||||
dependencies (#239)
|
||||
|
||||
|
||||
## New with 1.0.29 (released 2020-02-02)
|
||||
|
|
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
|
||||
|
||||
|
@ -514,11 +528,9 @@ libsane_fujitsu_la_LIBADD = $(COMMON_LIBS) libfujitsu.la ../sanei/sanei_init_deb
|
|||
EXTRA_DIST += fujitsu.conf.in
|
||||
|
||||
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 \
|
||||
genesys/error.h genesys/error.cpp \
|
||||
|
@ -526,6 +538,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 \
|
||||
|
@ -546,6 +559,7 @@ 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_sensor.cpp \
|
||||
|
@ -554,6 +568,7 @@ libgenesys_la_SOURCES = genesys/genesys.cpp genesys/genesys.h \
|
|||
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
|
||||
|
@ -561,7 +576,10 @@ libgenesys_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=genesys
|
|||
nodist_libsane_genesys_la_SOURCES = genesys-s.cpp
|
||||
libsane_genesys_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=genesys
|
||||
libsane_genesys_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_genesys_la_LIBADD = $(COMMON_LIBS) libgenesys.la ../sanei/sanei_magic.lo ../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)
|
||||
libsane_genesys_la_LIBADD = $(COMMON_LIBS) libgenesys.la \
|
||||
../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \
|
||||
../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo \
|
||||
$(MATH_LIB) $(TIFF_LIBS) $(USB_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += genesys.conf.in
|
||||
|
||||
libgphoto2_i_la_SOURCES = gphoto2.c gphoto2.h
|
||||
|
@ -695,10 +713,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
|
||||
|
@ -917,12 +935,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
|
||||
|
|
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;
|
||||
|
|
|
@ -32,11 +32,12 @@
|
|||
|
||||
#include "sane/sanei_debug.h"
|
||||
|
||||
static int
|
||||
static ssize_t
|
||||
sanei_epson_net_read_raw(Epson_Scanner *s, unsigned char *buf, ssize_t wanted,
|
||||
SANE_Status *status)
|
||||
{
|
||||
int ready, read = -1;
|
||||
int ready;
|
||||
ssize_t read = -1;
|
||||
fd_set readable;
|
||||
struct timeval tv;
|
||||
|
||||
|
@ -62,111 +63,136 @@ sanei_epson_net_read_raw(Epson_Scanner *s, unsigned char *buf, ssize_t wanted,
|
|||
return read;
|
||||
}
|
||||
|
||||
int
|
||||
static ssize_t
|
||||
sanei_epson_net_read_buf(Epson_Scanner *s, unsigned char *buf, ssize_t wanted,
|
||||
SANE_Status * status)
|
||||
{
|
||||
ssize_t read = 0;
|
||||
|
||||
DBG(23, "%s: reading up to %lu from buffer at %p, %lu available\n",
|
||||
__func__, (u_long) wanted, s->netptr, (u_long) s->netlen);
|
||||
|
||||
if ((size_t) wanted > s->netlen) {
|
||||
*status = SANE_STATUS_IO_ERROR;
|
||||
wanted = s->netlen;
|
||||
}
|
||||
|
||||
memcpy(buf, s->netptr, wanted);
|
||||
read = wanted;
|
||||
|
||||
s->netptr += read;
|
||||
s->netlen -= read;
|
||||
|
||||
if (s->netlen == 0) {
|
||||
DBG(23, "%s: freeing %p\n", __func__, s->netbuf);
|
||||
free(s->netbuf);
|
||||
s->netbuf = s->netptr = NULL;
|
||||
s->netlen = 0;
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
sanei_epson_net_read(Epson_Scanner *s, unsigned char *buf, ssize_t wanted,
|
||||
SANE_Status * status)
|
||||
{
|
||||
ssize_t size;
|
||||
ssize_t read = 0;
|
||||
unsigned char header[12];
|
||||
|
||||
/* read from buffer, if available */
|
||||
if (s->netptr != s->netbuf) {
|
||||
DBG(23, "reading %lu from buffer at %p, %lu available\n",
|
||||
(u_long) wanted, s->netptr, (u_long) s->netlen);
|
||||
|
||||
memcpy(buf, s->netptr, wanted);
|
||||
read = wanted;
|
||||
|
||||
s->netlen -= wanted;
|
||||
|
||||
if (s->netlen == 0) {
|
||||
DBG(23, "%s: freeing %p\n", __func__, s->netbuf);
|
||||
free(s->netbuf);
|
||||
s->netbuf = s->netptr = NULL;
|
||||
s->netlen = 0;
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
/* receive net header */
|
||||
size = sanei_epson_net_read_raw(s, header, 12, status);
|
||||
if (size != 12) {
|
||||
if (wanted < 0) {
|
||||
*status = SANE_STATUS_INVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t size;
|
||||
ssize_t read = 0;
|
||||
unsigned char header[12];
|
||||
|
||||
/* read from remainder of buffer */
|
||||
if (s->netptr) {
|
||||
return sanei_epson_net_read_buf(s, buf, wanted, status);
|
||||
}
|
||||
|
||||
/* receive net header */
|
||||
read = sanei_epson_net_read_raw(s, header, 12, status);
|
||||
if (read != 12) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* validate header */
|
||||
if (header[0] != 'I' || header[1] != 'S') {
|
||||
DBG(1, "header mismatch: %02X %02x\n", header[0], header[1]);
|
||||
*status = SANE_STATUS_IO_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* parse payload size */
|
||||
size = be32atoh(&header[6]);
|
||||
|
||||
DBG(23, "%s: wanted = %lu, available = %lu\n", __func__,
|
||||
(u_long) wanted, (u_long) size);
|
||||
|
||||
*status = SANE_STATUS_GOOD;
|
||||
|
||||
if (size == wanted) {
|
||||
if (!s->netbuf) {
|
||||
DBG(15, "%s: direct read\n", __func__);
|
||||
DBG(23, "%s: wanted = %lu, available = %lu\n", __func__,
|
||||
(u_long) wanted, (u_long) size);
|
||||
|
||||
DBG(15, "%s: full read\n", __func__);
|
||||
|
||||
read = sanei_epson_net_read_raw(s, buf, size, status);
|
||||
|
||||
if (s->netbuf) {
|
||||
free(s->netbuf);
|
||||
s->netbuf = NULL;
|
||||
s->netlen = 0;
|
||||
if ((size_t) wanted > size) {
|
||||
wanted = size;
|
||||
}
|
||||
|
||||
if (read < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* } else if (wanted < size && s->netlen == size) { */
|
||||
read = sanei_epson_net_read_raw(s, buf, wanted, status);
|
||||
} else {
|
||||
DBG(23, "%s: partial read\n", __func__);
|
||||
DBG(15, "%s: buffered read\n", __func__);
|
||||
DBG(23, "%s: bufferable = %lu, available = %lu\n", __func__,
|
||||
(u_long) s->netlen, (u_long) size);
|
||||
|
||||
read = sanei_epson_net_read_raw(s, s->netbuf, size, status);
|
||||
if (read != size) {
|
||||
return 0;
|
||||
if (s->netlen > size) {
|
||||
s->netlen = size;
|
||||
}
|
||||
|
||||
s->netlen = size - wanted;
|
||||
s->netptr += wanted;
|
||||
read = wanted;
|
||||
/* fill buffer */
|
||||
read = sanei_epson_net_read_raw(s, s->netbuf, s->netlen, status);
|
||||
s->netptr = s->netbuf;
|
||||
s->netlen = (read > 0 ? read : 0);
|
||||
|
||||
DBG(23, "0,4 %02x %02x\n", s->netbuf[0], s->netbuf[4]);
|
||||
DBG(23, "storing %lu to buffer at %p, next read at %p, %lu bytes left\n",
|
||||
(u_long) size, s->netbuf, s->netptr, (u_long) s->netlen);
|
||||
|
||||
memcpy(buf, s->netbuf, wanted);
|
||||
/* copy wanted part */
|
||||
read = sanei_epson_net_read_buf(s, buf, wanted, status);
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
size_t
|
||||
sanei_epson_net_write(Epson_Scanner *s, unsigned int cmd, const unsigned char *buf,
|
||||
size_t buf_size, size_t reply_len, SANE_Status *status)
|
||||
{
|
||||
unsigned char *h1, *h2, *payload;
|
||||
unsigned char *packet = malloc(12 + 8 + buf_size);
|
||||
|
||||
/* XXX check allocation failure */
|
||||
if (!packet) {
|
||||
*status = SANE_STATUS_NO_MEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
h1 = packet;
|
||||
h2 = packet + 12;
|
||||
payload = packet + 12 + 8;
|
||||
|
||||
if (reply_len) {
|
||||
s->netbuf = s->netptr = malloc(reply_len);
|
||||
if (s->netbuf) {
|
||||
DBG(23, "%s, freeing %p, %ld bytes unprocessed\n",
|
||||
__func__, s->netbuf, (u_long) s->netlen);
|
||||
free(s->netbuf);
|
||||
s->netbuf = s->netptr = NULL;
|
||||
s->netlen = 0;
|
||||
}
|
||||
s->netbuf = malloc(reply_len);
|
||||
if (!s->netbuf) {
|
||||
free(packet);
|
||||
*status = SANE_STATUS_NO_MEM;
|
||||
return 0;
|
||||
}
|
||||
s->netlen = reply_len;
|
||||
DBG(24, "allocated %lu bytes at %p\n",
|
||||
(u_long) reply_len, s->netbuf);
|
||||
DBG(24, "%s: allocated %lu bytes at %p\n", __func__,
|
||||
(u_long) s->netlen, s->netbuf);
|
||||
}
|
||||
|
||||
DBG(24, "%s: cmd = %04x, buf = %p, buf_size = %lu, reply_len = %lu\n",
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
#include <sys/types.h>
|
||||
#include "../include/sane/sane.h"
|
||||
|
||||
extern int sanei_epson_net_read(struct Epson_Scanner *s, unsigned char *buf, ssize_t buf_size,
|
||||
extern ssize_t sanei_epson_net_read(struct Epson_Scanner *s, unsigned char *buf, ssize_t buf_size,
|
||||
SANE_Status *status);
|
||||
extern int sanei_epson_net_write(struct Epson_Scanner *s, unsigned int cmd, const unsigned char *buf,
|
||||
extern size_t sanei_epson_net_write(struct Epson_Scanner *s, unsigned int cmd, const unsigned char *buf,
|
||||
size_t buf_size, size_t reply_len,
|
||||
SANE_Status *status);
|
||||
extern SANE_Status sanei_epson_net_lock(struct Epson_Scanner *s);
|
||||
|
|
|
@ -117,7 +117,7 @@ esci2_check_header(const char *cmd, const char *buf, unsigned int *more)
|
|||
return 0;
|
||||
}
|
||||
|
||||
err = sscanf(&buf[5], "%x#", more);
|
||||
err = sscanf(&buf[5], "%7x#", more);
|
||||
if (err != 1) {
|
||||
DBG(1, "cannot decode length from header\n");
|
||||
return 0;
|
||||
|
@ -193,6 +193,8 @@ static SANE_Status esci2_cmd(epsonds_scanner* s,
|
|||
|
||||
ssize_t read = eds_recv(s, pbuf, more, &status);
|
||||
if (read != more) {
|
||||
free(pbuf);
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
}
|
||||
|
||||
/* parse the received data block */
|
||||
|
@ -255,18 +257,20 @@ static int decode_value(char *buf, int len)
|
|||
}
|
||||
|
||||
/* h000 */
|
||||
static char *decode_binary(char *buf)
|
||||
static char *decode_binary(char *buf, int len)
|
||||
{
|
||||
char tmp[6];
|
||||
int hl;
|
||||
|
||||
memcpy(tmp, buf, 4);
|
||||
tmp[4] = '\0';
|
||||
len -= 4;
|
||||
|
||||
if (buf[0] != 'h')
|
||||
return NULL;
|
||||
|
||||
hl = strtol(tmp + 1, NULL, 16);
|
||||
if (hl > len) hl = len;
|
||||
if (hl) {
|
||||
|
||||
char *v = malloc(hl + 1);
|
||||
|
@ -279,9 +283,9 @@ static char *decode_binary(char *buf)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static char *decode_string(char *buf)
|
||||
static char *decode_string(char *buf, int len)
|
||||
{
|
||||
char *p, *s = decode_binary(buf);
|
||||
char *p, *s = decode_binary(buf, len);
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -326,20 +330,20 @@ static SANE_Status info_cb(void *userdata, char *token, int len)
|
|||
|
||||
if (strncmp("PRD", token, 3) == 0) {
|
||||
free(s->hw->model);
|
||||
s->hw->model = decode_string(value);
|
||||
s->hw->model = decode_string(value, len);
|
||||
s->hw->sane.model = s->hw->model;
|
||||
DBG(1, " product: %s\n", s->hw->model);
|
||||
/* we will free the string later */
|
||||
}
|
||||
|
||||
if (strncmp("VER", token, 3) == 0) {
|
||||
char *v = decode_string(value);
|
||||
char *v = decode_string(value, len);
|
||||
DBG(1, " version: %s\n", v);
|
||||
free(v);
|
||||
}
|
||||
|
||||
if (strncmp("S/N", token, 3) == 0) {
|
||||
char *v = decode_string(value);
|
||||
char *v = decode_string(value, len);
|
||||
DBG(1, " serial: %s\n", v);
|
||||
free(v);
|
||||
}
|
||||
|
@ -876,6 +880,11 @@ esci2_img(struct epsonds_scanner *s, SANE_Int *length)
|
|||
return parse_status;
|
||||
}
|
||||
|
||||
/* more data than was accounted for in s->buf */
|
||||
if (more > s->bsz) {
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
}
|
||||
|
||||
/* ALWAYS read image data */
|
||||
if (s->hw->connection == SANE_EPSONDS_NET) {
|
||||
epsonds_net_request_read(s, more);
|
||||
|
|
|
@ -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"
|
||||
|
@ -1230,16 +1232,18 @@ sane_start(SANE_Handle handle)
|
|||
if (s->line_buffer == NULL)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
|
||||
/* ring buffer for front page, twice bsz */
|
||||
/* transfer buffer size, bsz */
|
||||
/* XXX read value from scanner */
|
||||
status = eds_ring_init(&s->front, (65536 * 4) * 2);
|
||||
s->bsz = (65536 * 4);
|
||||
|
||||
/* ring buffer for front page */
|
||||
status = eds_ring_init(&s->front, s->bsz * 2);
|
||||
if (status != SANE_STATUS_GOOD) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* transfer buffer, bsz */
|
||||
/* XXX read value from scanner */
|
||||
s->buf = realloc(s->buf, 65536 * 4);
|
||||
/* transfer buffer */
|
||||
s->buf = realloc(s->buf, s->bsz);
|
||||
if (s->buf == NULL)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ usb
|
|||
# e.g.:
|
||||
# usb 0x4b8 0x14c
|
||||
|
||||
# Network
|
||||
# Network (not yet supported!)
|
||||
#
|
||||
# net 192.168.1.123
|
||||
net autodiscovery
|
||||
#net autodiscovery
|
||||
|
|
|
@ -160,6 +160,7 @@ struct epsonds_scanner
|
|||
Option_Value val[NUM_OPTIONS];
|
||||
SANE_Parameters params;
|
||||
|
||||
size_t bsz; /* transfer buffer size */
|
||||
SANE_Byte *buf, *line_buffer;
|
||||
ring_buffer *current, front, back;
|
||||
|
||||
|
|
|
@ -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
|
@ -64,6 +64,14 @@
|
|||
|
||||
#define ESCL_CONFIG_FILE "escl.conf"
|
||||
|
||||
|
||||
enum {
|
||||
PLATEN = 0,
|
||||
ADFSIMPLEX,
|
||||
ADFDUPLEX
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
int p1_0;
|
||||
int p2_0;
|
||||
|
@ -83,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;
|
||||
|
@ -105,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;
|
||||
|
@ -115,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 {
|
||||
|
@ -149,6 +170,9 @@ enum
|
|||
OPT_TL_Y,
|
||||
OPT_BR_X,
|
||||
OPT_BR_Y,
|
||||
|
||||
OPT_SCAN_SOURCE,
|
||||
|
||||
NUM_OPTIONS
|
||||
};
|
||||
|
||||
|
@ -158,13 +182,19 @@ enum
|
|||
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 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, SANE_String_Const name,
|
||||
SANE_Status escl_scan(capabilities_t *scanner, const ESCL_Device *device,
|
||||
char *result);
|
||||
void escl_scanner(SANE_String_Const name, 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);
|
||||
|
|
|
@ -141,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;
|
||||
|
@ -179,56 +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(!strcmp(scanner->DocumentFormats[i], "application/pdf"))
|
||||
else if(type == PLATEN && !strcmp(scanner->caps[type].DocumentFormats[i], "application/pdf"))
|
||||
{
|
||||
if (scanner->default_format)
|
||||
free(scanner->default_format);
|
||||
scanner->default_format = strdup("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);
|
||||
}
|
||||
|
||||
|
@ -242,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);
|
||||
}
|
||||
|
||||
|
@ -287,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 ||
|
||||
|
@ -306,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);
|
||||
}
|
||||
|
||||
|
@ -317,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".
|
||||
|
@ -339,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)
|
||||
|
@ -358,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);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ escl_crop_surface(capabilities_t *scanner,
|
|||
int *width,
|
||||
int *height)
|
||||
{
|
||||
double ratio = 1.0;
|
||||
int x_off = 0, x = 0;
|
||||
int real_w = 0;
|
||||
int y_off = 0, y = 0;
|
||||
|
@ -44,24 +45,31 @@ escl_crop_surface(capabilities_t *scanner,
|
|||
unsigned char *surface_crop = NULL;
|
||||
|
||||
DBG( 1, "Escl Image Crop\n");
|
||||
if (w < (int)scanner->width)
|
||||
scanner->width = w;
|
||||
if (scanner->pos_x < 0)
|
||||
scanner->pos_x = 0;
|
||||
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;
|
||||
|
||||
if (h < (int)scanner->height)
|
||||
scanner->height = h;
|
||||
if (scanner->pos_x < 0)
|
||||
scanner->pos_x = 0;
|
||||
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);
|
||||
|
||||
x_off = scanner->pos_x;
|
||||
real_w = scanner->width - x_off;
|
||||
y_off = scanner->pos_y;
|
||||
real_h = scanner->height - y_off;
|
||||
*width = real_w;
|
||||
*height = real_h;
|
||||
if (x_off > 0 || real_w < scanner->width ||
|
||||
y_off > 0 || real_h < scanner->height) {
|
||||
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) {
|
||||
|
@ -74,7 +82,12 @@ escl_crop_surface(capabilities_t *scanner,
|
|||
{
|
||||
for (x = 0; x < real_w; x++)
|
||||
{
|
||||
surface_crop[y * real_w + x] = surface[(y + y_off) * w + x + x_off];
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
@ -193,20 +192,39 @@ get_JPEG_data(capabilities_t *scanner, int *width, int *height, int *bps)
|
|||
cinfo.out_color_space = JCS_RGB;
|
||||
cinfo.quantize_colors = FALSE;
|
||||
jpeg_calc_output_dimensions(&cinfo);
|
||||
if (cinfo.output_width < (unsigned int)scanner->width)
|
||||
scanner->width = cinfo.output_width;
|
||||
if (scanner->pos_x < 0)
|
||||
scanner->pos_x = 0;
|
||||
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->height)
|
||||
scanner->height = cinfo.output_height;
|
||||
if (scanner->pos_y < 0)
|
||||
scanner->pos_y = 0;
|
||||
|
||||
x_off = scanner->pos_x;
|
||||
w = scanner->width - x_off;
|
||||
y_off = scanner->pos_y;
|
||||
h = scanner->height - y_off;
|
||||
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);
|
||||
|
@ -224,7 +242,7 @@ get_JPEG_data(capabilities_t *scanner, int *width, int *height, int *bps)
|
|||
if (y_off > 0)
|
||||
jpeg_skip_scanlines(&cinfo, y_off);
|
||||
pos = 0;
|
||||
while (cinfo.output_scanline < (unsigned int)scanner->height) {
|
||||
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++;
|
||||
|
|
|
@ -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,43 +159,55 @@ 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 {
|
||||
|
@ -221,14 +227,21 @@ escl_newjob (capabilities_t *scanner, SANE_String_Const name, SANE_Status *statu
|
|||
}
|
||||
}
|
||||
if (result == NULL) {
|
||||
DBG( 1, "Error : Create NewJob, no location\n");
|
||||
*status = SANE_STATUS_INVAL;
|
||||
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 {
|
||||
|
|
|
@ -140,8 +140,8 @@ get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps)
|
|||
}
|
||||
|
||||
poppler_page_get_size (page, &dw, &dh);
|
||||
dw = (double)scanner->default_resolution * dw / 72.0;
|
||||
dh = (double)scanner->default_resolution * dh / 72.0;
|
||||
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);
|
||||
|
@ -157,8 +157,8 @@ get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps)
|
|||
status = SANE_STATUS_INVAL;
|
||||
goto free_surface;
|
||||
}
|
||||
cairo_scale (cr, (double)scanner->default_resolution / 72.0,
|
||||
(double)scanner->default_resolution / 72.0);
|
||||
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);
|
||||
|
|
|
@ -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) {
|
||||
DBG(10, "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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,102 +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.
|
||||
*/
|
||||
|
||||
#include "buffer.h"
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace genesys {
|
||||
|
||||
void Genesys_Buffer::alloc(std::size_t size)
|
||||
{
|
||||
buffer_.resize(size);
|
||||
avail_ = 0;
|
||||
pos_ = 0;
|
||||
}
|
||||
|
||||
void Genesys_Buffer::clear()
|
||||
{
|
||||
buffer_.clear();
|
||||
avail_ = 0;
|
||||
pos_ = 0;
|
||||
}
|
||||
|
||||
void Genesys_Buffer::reset()
|
||||
{
|
||||
avail_ = 0;
|
||||
pos_ = 0;
|
||||
}
|
||||
|
||||
std::uint8_t* Genesys_Buffer::get_write_pos(std::size_t size)
|
||||
{
|
||||
if (avail_ + size > buffer_.size())
|
||||
return nullptr;
|
||||
if (pos_ + avail_ + size > buffer_.size())
|
||||
{
|
||||
std::memmove(buffer_.data(), buffer_.data() + pos_, avail_);
|
||||
pos_ = 0;
|
||||
}
|
||||
return buffer_.data() + pos_ + avail_;
|
||||
}
|
||||
|
||||
std::uint8_t* Genesys_Buffer::get_read_pos()
|
||||
{
|
||||
return buffer_.data() + pos_;
|
||||
}
|
||||
|
||||
void Genesys_Buffer::produce(std::size_t size)
|
||||
{
|
||||
if (size > buffer_.size() - avail_)
|
||||
throw std::runtime_error("buffer size exceeded");
|
||||
avail_ += size;
|
||||
}
|
||||
|
||||
void Genesys_Buffer::consume(std::size_t size)
|
||||
{
|
||||
if (size > avail_)
|
||||
throw std::runtime_error("no more data in buffer");
|
||||
avail_ -= size;
|
||||
pos_ += size;
|
||||
}
|
||||
|
||||
} // namespace genesys
|
|
@ -1,89 +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.
|
||||
*/
|
||||
|
||||
#ifndef BACKEND_GENESYS_BUFFER_H
|
||||
#define BACKEND_GENESYS_BUFFER_H
|
||||
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace genesys {
|
||||
|
||||
/* A FIFO buffer. Note, that this is _not_ a ringbuffer.
|
||||
if we need a block which does not fit at the end of our available data,
|
||||
we move the available data to the beginning.
|
||||
*/
|
||||
struct Genesys_Buffer
|
||||
{
|
||||
Genesys_Buffer() = default;
|
||||
|
||||
std::size_t size() const { return buffer_.size(); }
|
||||
std::size_t avail() const { return avail_; }
|
||||
std::size_t pos() const { return pos_; }
|
||||
|
||||
// TODO: refactor code that uses this function to no longer use it
|
||||
void set_pos(std::size_t pos) { pos_ = pos; }
|
||||
|
||||
void alloc(std::size_t size);
|
||||
void clear();
|
||||
|
||||
void reset();
|
||||
|
||||
std::uint8_t* get_write_pos(std::size_t size);
|
||||
std::uint8_t* get_read_pos(); // TODO: mark as const
|
||||
|
||||
void produce(std::size_t size);
|
||||
void consume(std::size_t size);
|
||||
|
||||
private:
|
||||
std::vector<std::uint8_t> buffer_;
|
||||
// current position in read buffer
|
||||
std::size_t pos_ = 0;
|
||||
// data bytes currently in buffer
|
||||
std::size_t avail_ = 0;
|
||||
};
|
||||
|
||||
} // namespace genesys
|
||||
|
||||
#endif // BACKEND_GENESYS_BUFFER_H
|
|
@ -67,13 +67,10 @@ 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_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,
|
||||
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
|
||||
|
@ -133,9 +130,6 @@ public:
|
|||
/// eject document from scanner
|
||||
virtual void eject_document(Genesys_Device* dev) const = 0;
|
||||
|
||||
/// move scanning head to transparency adapter
|
||||
virtual void move_to_ta(Genesys_Device* dev) const = 0;
|
||||
|
||||
/// write shading data calibration to ASIC
|
||||
virtual void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
std::uint8_t* data, int size) const = 0;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "command_set_common.h"
|
||||
#include "low.h"
|
||||
#include "value_filter.h"
|
||||
|
||||
namespace genesys {
|
||||
|
||||
|
@ -83,6 +84,7 @@ void CommandSetCommon::set_xpa_lamp_power(Genesys_Device& dev, bool set) const
|
|||
// turning off the lamp
|
||||
LampSettings settings[] = {
|
||||
{ ModelId::CANON_4400F, ScanMethod::TRANSPARENCY, {}, {} },
|
||||
{ ModelId::CANON_5600F, ScanMethod::TRANSPARENCY, {}, {} },
|
||||
{ ModelId::CANON_8400F, ScanMethod::TRANSPARENCY, {
|
||||
{ 0xa6, 0x34, 0xf4 },
|
||||
}, {
|
||||
|
@ -113,6 +115,7 @@ void CommandSetCommon::set_xpa_lamp_power(Genesys_Device& dev, bool set) const
|
|||
{ 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 },
|
||||
|
@ -121,6 +124,7 @@ void CommandSetCommon::set_xpa_lamp_power(Genesys_Device& dev, bool set) const
|
|||
}
|
||||
},
|
||||
{ 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 },
|
||||
|
@ -128,6 +132,13 @@ void CommandSetCommon::set_xpa_lamp_power(Genesys_Device& dev, bool set) const
|
|||
{ 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) {
|
||||
|
@ -150,7 +161,7 @@ void CommandSetCommon::set_motor_mode(Genesys_Device& dev, Genesys_Register_Set&
|
|||
|
||||
struct MotorSettings {
|
||||
ModelId model_id;
|
||||
ResolutionFilter resolutions;
|
||||
ValueFilterAny<unsigned> resolutions;
|
||||
GenesysRegisterSettingSet regs_primary_and_secondary;
|
||||
GenesysRegisterSettingSet regs_primary;
|
||||
GenesysRegisterSettingSet regs_secondary;
|
||||
|
@ -187,7 +198,7 @@ void CommandSetCommon::set_motor_mode(Genesys_Device& dev, Genesys_Register_Set&
|
|||
{ 0xa6, 0x01, 0x41 },
|
||||
}
|
||||
},
|
||||
{ ModelId::HP_SCANJET_G4050, ResolutionFilter::ANY, {
|
||||
{ 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
|
||||
|
@ -200,9 +211,12 @@ void CommandSetCommon::set_motor_mode(Genesys_Device& dev, Genesys_Register_Set&
|
|||
{ 0xa9, 0x00, 0x10 }, // note that 0x20 bit is not reset
|
||||
}, {}
|
||||
},
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7200I, ResolutionFilter::ANY, {}, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7300, ResolutionFilter::ANY, {}, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7500I, ResolutionFilter::ANY, {}, {}, {} },
|
||||
{ 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) {
|
||||
|
|
|
@ -1,238 +0,0 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2005, 2006 Pierre Willenbrock <pierre@pirsoft.dnsalias.org>
|
||||
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.
|
||||
*/
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
|
||||
#include "conv.h"
|
||||
#include "sane/sanei_magic.h"
|
||||
|
||||
namespace genesys {
|
||||
|
||||
/**
|
||||
* uses the threshold/threshold_curve to control software binarization
|
||||
* This code was taken from the epjistsu backend by m. allan noah
|
||||
* @param dev device set up for the scan
|
||||
* @param src pointer to raw data
|
||||
* @param dst pointer where to store result
|
||||
* @param width width of the processed line
|
||||
* */
|
||||
void binarize_line(Genesys_Device* dev, std::uint8_t* src, std::uint8_t* dst, int width)
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
int j, windowX, sum = 0;
|
||||
int thresh;
|
||||
int offset, addCol, dropCol;
|
||||
unsigned char mask;
|
||||
|
||||
int x;
|
||||
std::uint8_t min, max;
|
||||
|
||||
/* normalize line */
|
||||
min = 255;
|
||||
max = 0;
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
if (src[x] > max)
|
||||
{
|
||||
max = src[x];
|
||||
}
|
||||
if (src[x] < min)
|
||||
{
|
||||
min = src[x];
|
||||
}
|
||||
}
|
||||
|
||||
/* safeguard against dark or white areas */
|
||||
if(min>80)
|
||||
min=0;
|
||||
if(max<80)
|
||||
max=255;
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
src[x] = ((src[x] - min) * 255) / (max - min);
|
||||
}
|
||||
|
||||
/* ~1mm works best, but the window needs to have odd # of pixels */
|
||||
windowX = (6 * dev->settings.xres) / 150;
|
||||
if (!(windowX % 2))
|
||||
windowX++;
|
||||
|
||||
/* second, prefill the sliding sum */
|
||||
for (j = 0; j < windowX; j++)
|
||||
sum += src[j];
|
||||
|
||||
/* third, walk the input buffer, update the sliding sum, */
|
||||
/* determine threshold, output bits */
|
||||
for (j = 0; j < width; j++)
|
||||
{
|
||||
/* output image location */
|
||||
offset = j % 8;
|
||||
mask = 0x80 >> offset;
|
||||
thresh = dev->settings.threshold;
|
||||
|
||||
/* move sum/update threshold only if there is a curve */
|
||||
if (dev->settings.threshold_curve)
|
||||
{
|
||||
addCol = j + windowX / 2;
|
||||
dropCol = addCol - windowX;
|
||||
|
||||
if (dropCol >= 0 && addCol < width)
|
||||
{
|
||||
sum -= src[dropCol];
|
||||
sum += src[addCol];
|
||||
}
|
||||
thresh = dev->lineart_lut[sum / windowX];
|
||||
}
|
||||
|
||||
/* use average to lookup threshold */
|
||||
if (src[j] > thresh)
|
||||
*dst &= ~mask; /* white */
|
||||
else
|
||||
*dst |= mask; /* black */
|
||||
|
||||
if (offset == 7)
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* software lineart using data from a 8 bit gray scan. We assume true gray
|
||||
* or monochrome scan as input.
|
||||
*/
|
||||
void genesys_gray_lineart(Genesys_Device* dev,
|
||||
std::uint8_t* src_data, std::uint8_t* dst_data,
|
||||
std::size_t pixels, std::size_t lines, std::uint8_t threshold)
|
||||
{
|
||||
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);
|
||||
|
||||
for (y = 0; y < lines; y++)
|
||||
{
|
||||
binarize_line (dev, src_data + y * pixels, dst_data, pixels);
|
||||
dst_data += pixels / 8;
|
||||
}
|
||||
}
|
||||
|
||||
/** Look in image for likely left/right/bottom paper edges, then crop image.
|
||||
*/
|
||||
void genesys_crop(Genesys_Scanner* s)
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
Genesys_Device *dev = s->dev;
|
||||
int top = 0;
|
||||
int bottom = 0;
|
||||
int left = 0;
|
||||
int right = 0;
|
||||
|
||||
// first find edges if any
|
||||
TIE(sanei_magic_findEdges(&s->params, dev->img_buffer.data(),
|
||||
dev->settings.xres, dev->settings.yres,
|
||||
&top, &bottom, &left, &right));
|
||||
|
||||
DBG (DBG_io, "%s: t:%d b:%d l:%d r:%d\n", __func__, top, bottom, left,
|
||||
right);
|
||||
|
||||
// now crop the image
|
||||
TIE(sanei_magic_crop (&(s->params), dev->img_buffer.data(), top, bottom, left, right));
|
||||
|
||||
/* update counters to new image size */
|
||||
dev->total_bytes_to_read = s->params.bytes_per_line * s->params.lines;
|
||||
}
|
||||
|
||||
/** Look in image for likely upper and left paper edges, then rotate
|
||||
* image so that upper left corner of paper is upper left of image.
|
||||
*/
|
||||
void genesys_deskew(Genesys_Scanner *s, const Genesys_Sensor& sensor)
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
Genesys_Device *dev = s->dev;
|
||||
|
||||
int x = 0, y = 0, bg;
|
||||
double slope = 0;
|
||||
|
||||
bg=0;
|
||||
if(s->params.format==SANE_FRAME_GRAY && s->params.depth == 1)
|
||||
{
|
||||
bg=0xff;
|
||||
}
|
||||
TIE(sanei_magic_findSkew(&s->params, dev->img_buffer.data(),
|
||||
sensor.optical_res, sensor.optical_res,
|
||||
&x, &y, &slope));
|
||||
|
||||
DBG(DBG_info, "%s: slope=%f => %f\n", __func__, slope, slope * 180 / M_PI);
|
||||
|
||||
// rotate image slope is in [-PI/2,PI/2]. Positive values rotate trigonometric direction wise
|
||||
TIE(sanei_magic_rotate(&s->params, dev->img_buffer.data(),
|
||||
x, y, slope, bg));
|
||||
}
|
||||
|
||||
/** remove lone dots
|
||||
*/
|
||||
void genesys_despeck(Genesys_Scanner* s)
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
TIE(sanei_magic_despeck(&s->params, s->dev->img_buffer.data(), s->despeck));
|
||||
}
|
||||
|
||||
/** Look if image needs rotation and apply it
|
||||
* */
|
||||
void genesys_derotate(Genesys_Scanner* s)
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
int angle = 0;
|
||||
|
||||
TIE(sanei_magic_findTurn(&s->params, s->dev->img_buffer.data(),
|
||||
s->resolution, s->resolution, &angle));
|
||||
|
||||
// apply rotation angle found
|
||||
TIE(sanei_magic_turn(&s->params, s->dev->img_buffer.data(), angle));
|
||||
|
||||
// update counters to new image size
|
||||
s->dev->total_bytes_to_read = s->params.bytes_per_line * s->params.lines;
|
||||
}
|
||||
|
||||
} // namespace genesys
|
|
@ -1,69 +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.
|
||||
*/
|
||||
|
||||
#ifndef BACKEND_GENESYS_CONV_H
|
||||
#define BACKEND_GENESYS_CONV_H
|
||||
|
||||
#include "device.h"
|
||||
#include "sensor.h"
|
||||
#include "genesys.h"
|
||||
|
||||
namespace genesys {
|
||||
|
||||
void binarize_line(Genesys_Device* dev, std::uint8_t* src, std::uint8_t* dst, int width);
|
||||
|
||||
void genesys_gray_lineart(Genesys_Device* dev,
|
||||
std::uint8_t* src_data, std::uint8_t* dst_data,
|
||||
std::size_t pixels, size_t lines, std::uint8_t threshold);
|
||||
|
||||
void genesys_crop(Genesys_Scanner* s);
|
||||
|
||||
void genesys_deskew(Genesys_Scanner *s, const Genesys_Sensor& sensor);
|
||||
|
||||
void genesys_despeck(Genesys_Scanner* s);
|
||||
|
||||
void genesys_derotate(Genesys_Scanner* s);
|
||||
|
||||
} // namespace genesys
|
||||
|
||||
#endif // BACKEND_GENESYS_CONV_H
|
|
@ -102,10 +102,6 @@ Genesys_Device::~Genesys_Device()
|
|||
|
||||
void Genesys_Device::clear()
|
||||
{
|
||||
read_buffer.clear();
|
||||
binarize_buffer.clear();
|
||||
local_buffer.clear();
|
||||
|
||||
calib_file.clear();
|
||||
|
||||
calibration_cache.clear();
|
||||
|
@ -114,9 +110,9 @@ void Genesys_Device::clear()
|
|||
dark_average_data.clear();
|
||||
}
|
||||
|
||||
ImagePipelineNodeBytesSource& Genesys_Device::get_pipeline_source()
|
||||
ImagePipelineNodeBufferedCallableSource& Genesys_Device::get_pipeline_source()
|
||||
{
|
||||
return static_cast<ImagePipelineNodeBytesSource&>(pipeline.front());
|
||||
return static_cast<ImagePipelineNodeBufferedCallableSource&>(pipeline.front());
|
||||
}
|
||||
|
||||
bool Genesys_Device::is_head_pos_known(ScanHeadId scan_head) const
|
||||
|
@ -227,8 +223,12 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev)
|
|||
<< " 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'
|
||||
<< " 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]) << ' '
|
||||
|
@ -254,24 +254,26 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev)
|
|||
<< " read_active: " << dev.read_active << '\n'
|
||||
<< " parking: " << dev.parking << '\n'
|
||||
<< " document: " << dev.document << '\n'
|
||||
<< " read_buffer.size(): " << dev.read_buffer.size() << '\n'
|
||||
<< " binarize_buffer.size(): " << dev.binarize_buffer.size() << '\n'
|
||||
<< " local_buffer.size(): " << dev.local_buffer.size() << '\n'
|
||||
<< " oe_buffer.size(): " << dev.oe_buffer.size() << '\n'
|
||||
<< " total_bytes_read: " << dev.total_bytes_read << '\n'
|
||||
<< " total_bytes_to_read: " << dev.total_bytes_to_read << '\n'
|
||||
<< " session: " << format_indent_braced_list(4, dev.session) << '\n'
|
||||
<< " lineart_lut: (not printed)\n"
|
||||
<< " calibration_cache: (not printed)\n"
|
||||
<< " line_count: " << dev.line_count << '\n'
|
||||
<< " segment_order: "
|
||||
<< format_indent_braced_list(4, format_vector_unsigned(4, dev.segment_order)) << '\n'
|
||||
<< " buffer_image: " << dev.buffer_image << '\n'
|
||||
<< " img_buffer.size(): " << dev.img_buffer.size() << '\n'
|
||||
<< '}';
|
||||
return out;
|
||||
}
|
||||
|
||||
void apply_reg_settings_to_device_write_only(Genesys_Device& dev,
|
||||
const GenesysRegisterSettingSet& regs)
|
||||
{
|
||||
GenesysRegisterSettingSet backup;
|
||||
for (const auto& reg : regs) {
|
||||
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);
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
|
||||
#include "calibration.h"
|
||||
#include "command_set.h"
|
||||
#include "buffer.h"
|
||||
#include "enums.h"
|
||||
#include "image_pipeline.h"
|
||||
#include "motor.h"
|
||||
|
@ -78,6 +77,17 @@ struct Genesys_Gpo
|
|||
GenesysRegisterSettingSet regs;
|
||||
};
|
||||
|
||||
struct MemoryLayout
|
||||
{
|
||||
// This is used on GL845, GL846, GL847 and GL124 which have special registers to define the
|
||||
// memory layout
|
||||
MemoryLayout() = default;
|
||||
|
||||
ValueFilter<ModelId> models;
|
||||
|
||||
GenesysRegisterSettingSet regs;
|
||||
};
|
||||
|
||||
struct MethodResolutions
|
||||
{
|
||||
std::vector<ScanMethod> methods;
|
||||
|
@ -89,6 +99,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());
|
||||
|
@ -186,7 +206,7 @@ struct Genesys_Model
|
|||
// Amount of feeding needed to eject document after finishing scanning in mm
|
||||
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;
|
||||
|
@ -244,8 +264,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
|
||||
|
@ -262,7 +282,7 @@ 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;
|
||||
|
@ -272,6 +292,7 @@ struct Genesys_Device
|
|||
Genesys_Settings settings;
|
||||
Genesys_Frontend frontend, frontend_initial;
|
||||
Genesys_Gpo gpo;
|
||||
MemoryLayout memory_layout;
|
||||
Genesys_Motor motor;
|
||||
std::uint8_t control[6] = {};
|
||||
|
||||
|
@ -296,13 +317,6 @@ struct Genesys_Device
|
|||
// for sheetfed scanner's, is TRUE when there is a document in the scanner
|
||||
bool document = false;
|
||||
|
||||
Genesys_Buffer read_buffer;
|
||||
|
||||
// buffer for digital lineart from gray data
|
||||
Genesys_Buffer binarize_buffer;
|
||||
// local buffer for gray data during dynamix lineart
|
||||
Genesys_Buffer local_buffer;
|
||||
|
||||
// total bytes read sent to frontend
|
||||
size_t total_bytes_read = 0;
|
||||
// total bytes read to be sent to frontend
|
||||
|
@ -311,9 +325,6 @@ struct Genesys_Device
|
|||
// contains computed data for the current setup
|
||||
ScanSession session;
|
||||
|
||||
// look up table used in dynamic rasterization
|
||||
unsigned char lineart_lut[256] = {};
|
||||
|
||||
Calibration calibration_cache;
|
||||
|
||||
// number of scan lines used during scan
|
||||
|
@ -322,22 +333,13 @@ struct Genesys_Device
|
|||
// array describing the order of the sub-segments of the sensor
|
||||
std::vector<unsigned> segment_order;
|
||||
|
||||
// buffer to handle even/odd data
|
||||
Genesys_Buffer oe_buffer = {};
|
||||
|
||||
// stores information about how the input image should be processed
|
||||
ImagePipelineStack pipeline;
|
||||
|
||||
// an buffer that allows reading from `pipeline` in chunks of any size
|
||||
ImageBuffer pipeline_buffer;
|
||||
|
||||
// when true the scanned picture is first buffered to allow software image enhancements
|
||||
bool buffer_image = false;
|
||||
|
||||
// image buffer where the scanned picture is stored
|
||||
std::vector<std::uint8_t> img_buffer;
|
||||
|
||||
ImagePipelineNodeBytesSource& get_pipeline_source();
|
||||
ImagePipelineNodeBufferedCallableSource& get_pipeline_source();
|
||||
|
||||
std::unique_ptr<ScannerInterface> interface;
|
||||
|
||||
|
@ -365,6 +367,8 @@ 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);
|
||||
|
|
|
@ -109,6 +109,243 @@ 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, SensorId id)
|
||||
{
|
||||
switch (id) {
|
||||
case SensorId::CCD_5345: out << "CCD_5345"; break;
|
||||
case SensorId::CCD_CANON_4400F: out << "CCD_CANON_4400F"; break;
|
||||
case SensorId::CCD_CANON_5600F: out << "CCD_CANON_5600F"; break;
|
||||
case SensorId::CCD_CANON_8400F: out << "CCD_CANON_8400F"; break;
|
||||
case SensorId::CCD_CANON_8600F: out << "CCD_CANON_8600F"; break;
|
||||
case SensorId::CCD_DP665: out << "CCD_DP665"; break;
|
||||
case SensorId::CCD_DP685: out << "CCD_DP685"; break;
|
||||
case SensorId::CCD_DSMOBILE600: out << "CCD_DSMOBILE600"; break;
|
||||
case SensorId::CCD_DOCKETPORT_487: out << "CCD_DOCKETPORT_487"; break;
|
||||
case SensorId::CCD_G4050: out << "CCD_G4050"; break;
|
||||
case SensorId::CCD_HP2300: out << "CCD_HP2300"; break;
|
||||
case SensorId::CCD_HP2400: out << "CCD_HP2400"; break;
|
||||
case SensorId::CCD_HP3670: out << "CCD_HP3670"; break;
|
||||
case SensorId::CCD_HP_N6310: out << "CCD_HP_N6310"; break;
|
||||
case SensorId::CCD_HP_4850C: out << "CCD_HP_4850C"; break;
|
||||
case SensorId::CCD_IMG101: out << "CCD_IMG101"; break;
|
||||
case SensorId::CCD_KVSS080: out << "CCD_KVSS080"; break;
|
||||
case SensorId::CCD_PLUSTEK_OPTICBOOK_3800: out << "CCD_PLUSTEK_OPTICBOOK_3800"; break;
|
||||
case SensorId::CCD_PLUSTEK_OPTICFILM_7200: out << "CCD_PLUSTEK_OPTICFILM_7200"; break;
|
||||
case SensorId::CCD_PLUSTEK_OPTICFILM_7200I: out << "CCD_PLUSTEK_OPTICFILM_7200I"; break;
|
||||
case SensorId::CCD_PLUSTEK_OPTICFILM_7300: out << "CCD_PLUSTEK_OPTICFILM_7300"; break;
|
||||
case SensorId::CCD_PLUSTEK_OPTICFILM_7400: out << "CCD_PLUSTEK_OPTICFILM_7400"; break;
|
||||
case SensorId::CCD_PLUSTEK_OPTICFILM_7500I: out << "CCD_PLUSTEK_OPTICFILM_7500I"; break;
|
||||
case SensorId::CCD_PLUSTEK_OPTICFILM_8200I: out << "CCD_PLUSTEK_OPTICFILM_8200I"; break;
|
||||
case SensorId::CCD_PLUSTEK_OPTICPRO_3600: out << "CCD_PLUSTEK_OPTICPRO_3600"; break;
|
||||
case SensorId::CCD_ROADWARRIOR: out << "CCD_ROADWARRIOR"; break;
|
||||
case SensorId::CCD_ST12: out << "CCD_ST12"; break;
|
||||
case SensorId::CCD_ST24: out << "CCD_ST24"; break;
|
||||
case SensorId::CCD_UMAX: out << "CCD_UMAX"; break;
|
||||
case SensorId::CCD_XP300: out << "CCD_XP300"; break;
|
||||
case SensorId::CIS_CANON_LIDE_35: out << "CIS_CANON_LIDE_35"; break;
|
||||
case SensorId::CIS_CANON_LIDE_60: out << "CIS_CANON_LIDE_60"; break;
|
||||
case SensorId::CIS_CANON_LIDE_80: out << "CIS_CANON_LIDE_80"; break;
|
||||
case SensorId::CIS_CANON_LIDE_100: out << "CIS_CANON_LIDE_100"; break;
|
||||
case SensorId::CIS_CANON_LIDE_110: out << "CIS_CANON_LIDE_110"; break;
|
||||
case SensorId::CIS_CANON_LIDE_120: out << "CIS_CANON_LIDE_120"; break;
|
||||
case SensorId::CIS_CANON_LIDE_200: out << "CIS_CANON_LIDE_200"; break;
|
||||
case SensorId::CIS_CANON_LIDE_210: out << "CIS_CANON_LIDE_210"; break;
|
||||
case SensorId::CIS_CANON_LIDE_220: out << "CIS_CANON_LIDE_220"; break;
|
||||
case SensorId::CIS_CANON_LIDE_700F: out << "CIS_CANON_LIDE_700F"; break;
|
||||
case SensorId::CIS_XP200: out << "CIS_XP200"; 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_5600F: out << "CANON_5600F"; 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_7200: out << "PLUSTEK_OPTICFILM_7200"; 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_5600F: out << "CANON_5600F"; 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_5600F: out << "CANON_5600F"; 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_7200: out << "PLUSTEK_OPTICFILM_7200"; 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,16 +225,33 @@ 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,
|
||||
CCD_5345,
|
||||
CCD_CANON_4400F,
|
||||
CCD_CANON_5600F,
|
||||
CCD_CANON_8400F,
|
||||
CCD_CANON_8600F,
|
||||
CCD_DP665,
|
||||
CCD_DP685,
|
||||
CCD_DSMOBILE600,
|
||||
CCD_DOCKETPORT_487,
|
||||
CCD_G4050,
|
||||
CCD_HP2300,
|
||||
CCD_HP2400,
|
||||
|
@ -241,9 +261,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 +274,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,
|
||||
|
@ -275,6 +299,8 @@ inline void serialize(std::ostream& str, SensorId& x)
|
|||
serialize(str, value);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, SensorId id);
|
||||
|
||||
|
||||
enum class AdcId : unsigned
|
||||
{
|
||||
|
@ -287,15 +313,19 @@ enum class AdcId : unsigned
|
|||
CANON_LIDE_200,
|
||||
CANON_LIDE_700F,
|
||||
CANON_4400F,
|
||||
CANON_5600F,
|
||||
CANON_8400F,
|
||||
CANON_8600F,
|
||||
G4050,
|
||||
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 +351,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,
|
||||
|
@ -332,6 +364,7 @@ enum class GpioId : unsigned
|
|||
CANON_LIDE_210,
|
||||
CANON_LIDE_700F,
|
||||
CANON_4400F,
|
||||
CANON_5600F,
|
||||
CANON_8400F,
|
||||
CANON_8600F,
|
||||
DP665,
|
||||
|
@ -345,9 +378,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 +392,8 @@ enum class GpioId : unsigned
|
|||
XP300,
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, GpioId id);
|
||||
|
||||
enum class MotorId : unsigned
|
||||
{
|
||||
UNKNOWN = 0,
|
||||
|
@ -365,9 +403,11 @@ enum class MotorId : unsigned
|
|||
CANON_LIDE_200,
|
||||
CANON_LIDE_210,
|
||||
CANON_LIDE_35,
|
||||
CANON_LIDE_60,
|
||||
CANON_LIDE_700,
|
||||
CANON_LIDE_80,
|
||||
CANON_4400F,
|
||||
CANON_5600F,
|
||||
CANON_8400F,
|
||||
CANON_8600F,
|
||||
DP665,
|
||||
|
@ -380,9 +420,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 +434,8 @@ enum class MotorId : unsigned
|
|||
XP300,
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, MotorId id);
|
||||
|
||||
enum class StepType : unsigned
|
||||
{
|
||||
FULL = 0,
|
||||
|
@ -423,6 +468,7 @@ enum class AsicType : unsigned
|
|||
UNKNOWN = 0,
|
||||
GL646,
|
||||
GL841,
|
||||
GL842,
|
||||
GL843,
|
||||
GL845,
|
||||
GL846,
|
||||
|
@ -442,15 +488,25 @@ enum class ModelFlag : unsigned
|
|||
// use 14-bit gamma table instead of 12-bit
|
||||
GAMMA_14BIT = 1 << 1,
|
||||
|
||||
// skip lamp warmup (genesys_warmup())
|
||||
SKIP_WARMUP = 1 << 4,
|
||||
// perform lamp warmup
|
||||
WARMUP = 1 << 4,
|
||||
|
||||
// repark head and check for lock by moving without scanning
|
||||
REPARK = 1 << 7,
|
||||
// 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,
|
||||
|
||||
// host-side calibration uses a complete scan
|
||||
HOST_SIDE_CALIBRATION_COMPLETE_SCAN = 1 << 9,
|
||||
|
||||
// whether scanner must wait for the head while parking
|
||||
MUST_WAIT = 1 << 10,
|
||||
|
||||
|
@ -460,23 +516,23 @@ enum class ModelFlag : unsigned
|
|||
// allow custom gamma tables
|
||||
CUSTOM_GAMMA = 1 << 13,
|
||||
|
||||
// skip calibration completely, this is needed for sheet-fed scanners
|
||||
NO_CALIBRATION = 1 << 14,
|
||||
|
||||
// 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 always uses maximum hwdpi to setup the sensor
|
||||
FULL_HWDPI_MODE = 1 << 19,
|
||||
// the scanner outputs inverted pixel data
|
||||
INVERT_PIXEL_DATA = 1 << 19,
|
||||
|
||||
// the scanner outputs 16-bit data that is byte-inverted
|
||||
INVERTED_16BIT_DATA = 1 << 20,
|
||||
SWAP_16BIT_DATA = 1 << 20,
|
||||
|
||||
// the scanner has transparency, but it's implemented using only one motor
|
||||
UTA_NO_SECONDARY_MOTOR = 1 << 21
|
||||
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)
|
||||
|
@ -522,8 +578,10 @@ enum class ScanFlag : unsigned
|
|||
FEEDING = 1 << 8,
|
||||
USE_XPA = 1 << 9,
|
||||
ENABLE_LEDADD = 1 << 10,
|
||||
USE_XCORRECTION = 1 << 11,
|
||||
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)
|
||||
|
@ -563,39 +621,6 @@ 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,
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -171,6 +172,27 @@ SANE_Status wrap_exceptions_to_status_code(const char* func, F&& function)
|
|||
}
|
||||
}
|
||||
|
||||
template<class F>
|
||||
SANE_Status wrap_exceptions_to_status_code_return(const char* func, F&& function)
|
||||
{
|
||||
try {
|
||||
return function();
|
||||
} catch (const SaneException& exc) {
|
||||
DBG(DBG_error, "%s: got error: %s\n", func, exc.what());
|
||||
return exc.status();
|
||||
} catch (const std::bad_alloc& exc) {
|
||||
(void) exc;
|
||||
DBG(DBG_error, "%s: failed to allocate memory\n", func);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
} catch (const std::exception& exc) {
|
||||
DBG(DBG_error, "%s: got uncaught exception: %s\n", func, exc.what());
|
||||
return SANE_STATUS_INVAL;
|
||||
} catch (...) {
|
||||
DBG(DBG_error, "%s: got unknown uncaught exception\n", func);
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
}
|
||||
|
||||
template<class F>
|
||||
void catch_all_exceptions(const char* func, F&& function)
|
||||
{
|
||||
|
|
|
@ -46,9 +46,6 @@
|
|||
|
||||
namespace genesys {
|
||||
|
||||
// buffer.h
|
||||
struct Genesys_Buffer;
|
||||
|
||||
// calibration.h
|
||||
struct Genesys_Calibration_Cache;
|
||||
|
||||
|
@ -74,7 +71,6 @@ class Image;
|
|||
|
||||
// image_buffer.h
|
||||
class ImageBuffer;
|
||||
class ImageBufferGenesysUsb;
|
||||
|
||||
// image_pipeline.h
|
||||
class ImagePipelineNode;
|
||||
|
@ -86,7 +82,7 @@ struct Pixel;
|
|||
struct RawPixel;
|
||||
|
||||
// low.h
|
||||
struct Genesys_USB_Device_Entry;
|
||||
struct UsbDeviceEntry;
|
||||
|
||||
// motor.h
|
||||
struct Genesys_Motor;
|
||||
|
@ -111,8 +107,6 @@ class ScannerInterfaceUsb;
|
|||
class TestScannerInterface;
|
||||
|
||||
// sensor.h
|
||||
class ScanMethodFilter;
|
||||
class ResolutionFilter;
|
||||
struct GenesysFrontendLayout;
|
||||
struct Genesys_Frontend;
|
||||
struct SensorExposure;
|
||||
|
@ -123,6 +117,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
|
@ -107,21 +107,12 @@ enum Genesys_Option
|
|||
OPT_GAMMA_VECTOR_R,
|
||||
OPT_GAMMA_VECTOR_G,
|
||||
OPT_GAMMA_VECTOR_B,
|
||||
OPT_SWDESKEW,
|
||||
OPT_SWCROP,
|
||||
OPT_SWDESPECK,
|
||||
OPT_DESPECK,
|
||||
OPT_SWSKIP,
|
||||
OPT_SWDEROTATE,
|
||||
OPT_BRIGHTNESS,
|
||||
OPT_CONTRAST,
|
||||
|
||||
OPT_EXTRAS_GROUP,
|
||||
OPT_LAMP_OFF_TIME,
|
||||
OPT_LAMP_OFF,
|
||||
OPT_THRESHOLD,
|
||||
OPT_THRESHOLD_CURVE,
|
||||
OPT_DISABLE_INTERPOLATION,
|
||||
OPT_COLOR_FILTER,
|
||||
OPT_CALIBRATION_FILE,
|
||||
OPT_EXPIRATION_TIME,
|
||||
|
@ -213,18 +204,9 @@ struct Genesys_Scanner
|
|||
// Option values
|
||||
SANE_Word bit_depth = 0;
|
||||
SANE_Word resolution = 0;
|
||||
bool preview = false;
|
||||
SANE_Word threshold = 0;
|
||||
SANE_Word threshold_curve = 0;
|
||||
bool disable_interpolation = false;
|
||||
bool preview = false; // TODO: currently not used
|
||||
bool lamp_off = false;
|
||||
SANE_Word lamp_off_time = 0;
|
||||
bool swdeskew = false;
|
||||
bool swcrop = false;
|
||||
bool swdespeck = false;
|
||||
bool swderotate = false;
|
||||
SANE_Word swskip = 0;
|
||||
SANE_Word despeck = 0;
|
||||
SANE_Word contrast = 0;
|
||||
SANE_Word brightness = 0;
|
||||
SANE_Word expiration_time = 0;
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -50,68 +50,6 @@
|
|||
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 CommandSetCommon
|
||||
{
|
||||
public:
|
||||
|
@ -122,15 +60,11 @@ 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;
|
||||
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;
|
||||
|
@ -171,8 +105,6 @@ public:
|
|||
|
||||
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;
|
||||
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -54,388 +54,6 @@
|
|||
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 ScanSession 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 CommandSetCommon
|
||||
{
|
||||
public:
|
||||
|
@ -446,15 +64,11 @@ 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;
|
||||
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;
|
||||
|
@ -491,8 +105,6 @@ public:
|
|||
|
||||
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;
|
||||
|
||||
|
|
|
@ -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
|
@ -60,15 +60,11 @@ 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;
|
||||
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;
|
||||
|
@ -99,14 +95,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 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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -0,0 +1,989 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2010-2013 Stéphane Voltz <stef.dev@free.fr>
|
||||
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.
|
||||
|
||||
As a special exception, the authors of SANE give permission for
|
||||
additional uses of the libraries contained in this release of SANE.
|
||||
*/
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
|
||||
#include "gl842_registers.h"
|
||||
#include "gl842.h"
|
||||
#include "test_settings.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace genesys {
|
||||
namespace gl842 {
|
||||
|
||||
static void gl842_init_registers(Genesys_Device& dev)
|
||||
{
|
||||
// Within this function SENSOR_DEF marker documents that a register is part
|
||||
// of the sensors definition and the actual value is set in
|
||||
// gl842_setup_sensor().
|
||||
|
||||
DBG_HELPER(dbg);
|
||||
|
||||
dev.reg.clear();
|
||||
|
||||
dev.reg.init_reg(0x01, 0x00);
|
||||
dev.reg.init_reg(0x02, 0x78);
|
||||
dev.reg.init_reg(0x03, 0xbf);
|
||||
dev.reg.init_reg(0x04, 0x22);
|
||||
dev.reg.init_reg(0x05, 0x48);
|
||||
|
||||
dev.reg.init_reg(0x06, 0xb8);
|
||||
|
||||
dev.reg.init_reg(0x07, 0x00);
|
||||
dev.reg.init_reg(0x08, 0x00);
|
||||
dev.reg.init_reg(0x09, 0x00);
|
||||
dev.reg.init_reg(0x0a, 0x00);
|
||||
dev.reg.init_reg(0x0d, 0x01);
|
||||
|
||||
dev.reg.init_reg(0x10, 0x00); // exposure, overwritten in scanner_setup_sensor() below
|
||||
dev.reg.init_reg(0x11, 0x00); // exposure, overwritten in scanner_setup_sensor() below
|
||||
dev.reg.init_reg(0x12, 0x00); // exposure, overwritten in scanner_setup_sensor() below
|
||||
dev.reg.init_reg(0x13, 0x00); // exposure, overwritten in scanner_setup_sensor() below
|
||||
dev.reg.init_reg(0x14, 0x00); // exposure, overwritten in scanner_setup_sensor() below
|
||||
dev.reg.init_reg(0x15, 0x00); // exposure, overwritten in scanner_setup_sensor() below
|
||||
|
||||
// CCD signal settings.
|
||||
dev.reg.init_reg(0x16, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x17, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x18, 0x00); // SENSOR_DEF
|
||||
|
||||
// EXPDMY[0:7]: Exposure time of dummy lines.
|
||||
dev.reg.init_reg(0x19, 0x00); // SENSOR_DEF
|
||||
|
||||
// Various CCD clock settings.
|
||||
dev.reg.init_reg(0x1a, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x1b, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x1c, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x1d, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x1e, 0x10); // WDTIME, LINESEL: setup during sensor and motor setup
|
||||
|
||||
dev.reg.init_reg(0x1f, 0x01);
|
||||
|
||||
dev.reg.init_reg(0x20, 0x27); // BUFSEL: buffer full condition
|
||||
|
||||
dev.reg.init_reg(0x21, 0x10); // STEPNO: set during motor setup
|
||||
dev.reg.init_reg(0x22, 0x10); // FWDSTEP: set during motor setup
|
||||
dev.reg.init_reg(0x23, 0x10); // BWDSTEP: set during motor setup
|
||||
dev.reg.init_reg(0x24, 0x10); // FASTNO: set during motor setup
|
||||
dev.reg.init_reg(0x25, 0x00); // LINCNT: set during motor setup
|
||||
dev.reg.init_reg(0x26, 0x00); // LINCNT: set during motor setup
|
||||
dev.reg.init_reg(0x27, 0x00); // LINCNT: set during motor setup
|
||||
|
||||
dev.reg.init_reg(0x29, 0xff); // LAMPPWM
|
||||
|
||||
dev.reg.init_reg(0x2c, 0x02); // DPISET: set during sensor setup
|
||||
dev.reg.init_reg(0x2d, 0x58); // DPISET: set during sensor setup
|
||||
|
||||
dev.reg.init_reg(0x2e, 0x80); // BWHI: black/white low threshdold
|
||||
dev.reg.init_reg(0x2f, 0x80); // BWLOW: black/white low threshold
|
||||
|
||||
dev.reg.init_reg(0x30, 0x00); // STRPIXEL: set during sensor setup
|
||||
dev.reg.init_reg(0x31, 0x49); // STRPIXEL: set during sensor setup
|
||||
dev.reg.init_reg(0x32, 0x53); // ENDPIXEL: set during sensor setup
|
||||
dev.reg.init_reg(0x33, 0xb9); // ENDPIXEL: set during sensor setup
|
||||
|
||||
dev.reg.init_reg(0x34, 0x13); // DUMMY: SENSOR_DEF
|
||||
dev.reg.init_reg(0x35, 0x00); // MAXWD: set during scan setup
|
||||
dev.reg.init_reg(0x36, 0x40); // MAXWD: set during scan setup
|
||||
dev.reg.init_reg(0x37, 0x00); // MAXWD: set during scan setup
|
||||
dev.reg.init_reg(0x38, 0x2a); // LPERIOD: SENSOR_DEF
|
||||
dev.reg.init_reg(0x39, 0xf8); // LPERIOD: SENSOR_DEF
|
||||
dev.reg.init_reg(0x3d, 0x00); // FEEDL: set during motor setup
|
||||
dev.reg.init_reg(0x3e, 0x00); // FEEDL: set during motor setup
|
||||
dev.reg.init_reg(0x3f, 0x01); // FEEDL: set during motor setup
|
||||
|
||||
dev.reg.init_reg(0x52, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x53, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x54, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x55, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x56, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x57, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x58, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x59, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x5a, 0x00); // SENSOR_DEF
|
||||
|
||||
dev.reg.init_reg(0x5e, 0x01); // DECSEL, STOPTIM
|
||||
dev.reg.init_reg(0x5f, 0x10); // FMOVDEC: set during motor setup
|
||||
|
||||
dev.reg.init_reg(0x60, 0x00); // Z1MOD: overwritten during motor setup
|
||||
dev.reg.init_reg(0x61, 0x00); // Z1MOD: overwritten during motor setup
|
||||
dev.reg.init_reg(0x62, 0x00); // Z1MOD: overwritten during motor setup
|
||||
dev.reg.init_reg(0x63, 0x00); // Z2MOD: overwritten during motor setup
|
||||
dev.reg.init_reg(0x64, 0x00); // Z2MOD: overwritten during motor setup
|
||||
dev.reg.init_reg(0x65, 0x00); // Z2MOD: overwritten during motor setup
|
||||
|
||||
dev.reg.init_reg(0x67, 0x7f); // STEPSEL, MTRPWM: overwritten during motor setup
|
||||
dev.reg.init_reg(0x68, 0x7f); // FSTPSEL, FASTPWM: overwritten during motor setup
|
||||
dev.reg.init_reg(0x69, 0x10); // FSHDEC: overwritten during motor setup
|
||||
dev.reg.init_reg(0x6a, 0x10); // FMOVNO: overwritten during motor setup
|
||||
|
||||
// 0x6b, 0x6c, 0x6d, 0x6e, 0x6f - set according to gpio tables. See gl842_init_gpio.
|
||||
|
||||
dev.reg.init_reg(0x70, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x71, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x72, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x73, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x74, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x75, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x76, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x77, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x78, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x79, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x7a, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x7b, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x7c, 0x00); // SENSOR_DEF
|
||||
dev.reg.init_reg(0x7d, 0x00); // SENSOR_DEF
|
||||
|
||||
// 0x7e - set according to gpio tables. See gl842_init_gpio.
|
||||
|
||||
dev.reg.init_reg(0x7f, 0x00); // SENSOR_DEF
|
||||
|
||||
// VRHOME, VRMOVE, VRBACK, VRSCAN: Vref settings of the motor driver IC for
|
||||
// moving in various situations.
|
||||
dev.reg.init_reg(0x80, 0x00); // MOTOR_PROFILE
|
||||
|
||||
dev.reg.init_reg(0x81, 0x00);
|
||||
dev.reg.init_reg(0x82, 0x00);
|
||||
dev.reg.init_reg(0x83, 0x00);
|
||||
dev.reg.init_reg(0x84, 0x00);
|
||||
dev.reg.init_reg(0x85, 0x00);
|
||||
dev.reg.init_reg(0x86, 0x00);
|
||||
dev.reg.init_reg(0x87, 0x00);
|
||||
|
||||
const auto& sensor = sanei_genesys_find_sensor_any(&dev);
|
||||
sanei_genesys_set_dpihw(dev.reg, sensor.register_dpihw);
|
||||
|
||||
scanner_setup_sensor(dev, sensor, dev.reg);
|
||||
}
|
||||
|
||||
static void gl842_set_ad_fe(Genesys_Device* dev)
|
||||
{
|
||||
for (const auto& reg : dev->frontend.regs) {
|
||||
dev->interface->write_fe_register(reg.address, reg.value);
|
||||
}
|
||||
}
|
||||
|
||||
// Set values of analog frontend
|
||||
void CommandSetGl842::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t set) const
|
||||
{
|
||||
DBG_HELPER_ARGS(dbg, "%s", set == AFE_INIT ? "init" :
|
||||
set == AFE_SET ? "set" :
|
||||
set == AFE_POWER_SAVE ? "powersave" : "huh?");
|
||||
(void) sensor;
|
||||
|
||||
if (set == AFE_INIT) {
|
||||
dev->frontend = dev->frontend_initial;
|
||||
}
|
||||
|
||||
// check analog frontend type
|
||||
// FIXME: looks like we write to that register with initial data
|
||||
uint8_t fe_type = dev->interface->read_register(REG_0x04) & REG_0x04_FESET;
|
||||
if (fe_type == 2) {
|
||||
gl842_set_ad_fe(dev);
|
||||
return;
|
||||
}
|
||||
if (fe_type != 0) {
|
||||
throw SaneException(SANE_STATUS_UNSUPPORTED, "unsupported frontend type %d", fe_type);
|
||||
}
|
||||
|
||||
for (unsigned i = 1; i <= 3; i++) {
|
||||
dev->interface->write_fe_register(i, dev->frontend.regs.get_value(0x00 + i));
|
||||
}
|
||||
for (const auto& reg : sensor.custom_fe_regs) {
|
||||
dev->interface->write_fe_register(reg.address, reg.value);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < 3; i++) {
|
||||
dev->interface->write_fe_register(0x20 + i, dev->frontend.get_offset(i));
|
||||
}
|
||||
|
||||
if (dev->model->sensor_id == SensorId::CCD_KVSS080) {
|
||||
for (unsigned i = 0; i < 3; i++) {
|
||||
dev->interface->write_fe_register(0x24 + i, dev->frontend.regs.get_value(0x24 + i));
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < 3; i++) {
|
||||
dev->interface->write_fe_register(0x28 + i, dev->frontend.get_gain(i));
|
||||
}
|
||||
}
|
||||
|
||||
static void gl842_init_motor_regs_scan(Genesys_Device* dev,
|
||||
const Genesys_Sensor& sensor,
|
||||
const ScanSession& session,
|
||||
Genesys_Register_Set* reg,
|
||||
const MotorProfile& motor_profile,
|
||||
unsigned int exposure,
|
||||
unsigned scan_yres,
|
||||
unsigned int scan_lines,
|
||||
unsigned int scan_dummy,
|
||||
unsigned int feed_steps,
|
||||
ScanFlag flags)
|
||||
{
|
||||
DBG_HELPER_ARGS(dbg, "exposure=%d, scan_yres=%d, step_type=%d, scan_lines=%d, scan_dummy=%d, "
|
||||
"feed_steps=%d, flags=%x",
|
||||
exposure, scan_yres, static_cast<unsigned>(motor_profile.step_type),
|
||||
scan_lines, scan_dummy, feed_steps, static_cast<unsigned>(flags));
|
||||
|
||||
unsigned step_multiplier = 2;
|
||||
bool use_fast_fed = false;
|
||||
|
||||
if ((scan_yres >= 300 && feed_steps > 900) || (has_flag(flags, ScanFlag::FEEDING))) {
|
||||
use_fast_fed = true;
|
||||
}
|
||||
|
||||
reg->set24(REG_LINCNT, scan_lines);
|
||||
|
||||
reg->set8(REG_0x02, 0);
|
||||
sanei_genesys_set_motor_power(*reg, true);
|
||||
|
||||
std::uint8_t reg02 = reg->get8(REG_0x02);
|
||||
if (use_fast_fed) {
|
||||
reg02 |= REG_0x02_FASTFED;
|
||||
} else {
|
||||
reg02 &= ~REG_0x02_FASTFED;
|
||||
}
|
||||
|
||||
// in case of automatic go home, move until home sensor
|
||||
if (has_flag(flags, ScanFlag::AUTO_GO_HOME)) {
|
||||
reg02 |= REG_0x02_AGOHOME | REG_0x02_NOTHOME;
|
||||
}
|
||||
|
||||
// disable backtracking if needed
|
||||
if (has_flag(flags, ScanFlag::DISABLE_BUFFER_FULL_MOVE) ||
|
||||
(scan_yres >= 2400) ||
|
||||
(scan_yres >= sensor.full_resolution))
|
||||
{
|
||||
reg02 |= REG_0x02_ACDCDIS;
|
||||
}
|
||||
|
||||
if (has_flag(flags, ScanFlag::REVERSE)) {
|
||||
reg02 |= REG_0x02_MTRREV;
|
||||
} else {
|
||||
reg02 &= ~REG_0x02_MTRREV;
|
||||
}
|
||||
reg->set8(REG_0x02, reg02);
|
||||
|
||||
// scan and backtracking slope table
|
||||
auto scan_table = create_slope_table(dev->model->asic_type, dev->motor, scan_yres, exposure,
|
||||
step_multiplier, motor_profile);
|
||||
|
||||
scanner_send_slope_table(dev, sensor, SCAN_TABLE, scan_table.table);
|
||||
scanner_send_slope_table(dev, sensor, BACKTRACK_TABLE, scan_table.table);
|
||||
scanner_send_slope_table(dev, sensor, STOP_TABLE, scan_table.table);
|
||||
|
||||
reg->set8(REG_STEPNO, scan_table.table.size() / step_multiplier);
|
||||
reg->set8(REG_FASTNO, scan_table.table.size() / step_multiplier);
|
||||
reg->set8(REG_FSHDEC, scan_table.table.size() / step_multiplier);
|
||||
|
||||
// fast table
|
||||
const auto* fast_profile = get_motor_profile_ptr(dev->motor.fast_profiles, 0, session);
|
||||
if (fast_profile == nullptr) {
|
||||
fast_profile = &motor_profile;
|
||||
}
|
||||
|
||||
auto fast_table = create_slope_table_fastest(dev->model->asic_type, step_multiplier,
|
||||
*fast_profile);
|
||||
|
||||
scanner_send_slope_table(dev, sensor, FAST_TABLE, fast_table.table);
|
||||
scanner_send_slope_table(dev, sensor, HOME_TABLE, fast_table.table);
|
||||
|
||||
reg->set8(REG_FMOVNO, fast_table.table.size() / step_multiplier);
|
||||
|
||||
if (motor_profile.motor_vref != -1 && fast_profile->motor_vref != 1) {
|
||||
std::uint8_t vref = 0;
|
||||
vref |= (motor_profile.motor_vref << REG_0x80S_TABLE1_NORMAL) & REG_0x80_TABLE1_NORMAL;
|
||||
vref |= (motor_profile.motor_vref << REG_0x80S_TABLE2_BACK) & REG_0x80_TABLE2_BACK;
|
||||
vref |= (fast_profile->motor_vref << REG_0x80S_TABLE4_FAST) & REG_0x80_TABLE4_FAST;
|
||||
vref |= (fast_profile->motor_vref << REG_0x80S_TABLE5_GO_HOME) & REG_0x80_TABLE5_GO_HOME;
|
||||
reg->set8(REG_0x80, vref);
|
||||
}
|
||||
|
||||
// substract acceleration distance from feedl
|
||||
unsigned feedl = feed_steps;
|
||||
feedl <<= static_cast<unsigned>(motor_profile.step_type);
|
||||
|
||||
unsigned dist = scan_table.table.size() / step_multiplier;
|
||||
|
||||
if (use_fast_fed) {
|
||||
dist += (fast_table.table.size() / step_multiplier) * 2;
|
||||
}
|
||||
|
||||
// make sure when don't insane value : XXX STEF XXX in this case we should
|
||||
// fall back to single table move
|
||||
if (dist < feedl) {
|
||||
feedl -= dist;
|
||||
} else {
|
||||
feedl = 1;
|
||||
}
|
||||
|
||||
reg->set24(REG_FEEDL, feedl);
|
||||
|
||||
// doesn't seem to matter that much
|
||||
std::uint32_t z1, z2;
|
||||
sanei_genesys_calculate_zmod(use_fast_fed,
|
||||
exposure,
|
||||
scan_table.table,
|
||||
scan_table.table.size() / step_multiplier,
|
||||
feedl,
|
||||
scan_table.table.size() / step_multiplier,
|
||||
&z1,
|
||||
&z2);
|
||||
if (scan_yres > 600) {
|
||||
z1 = 0;
|
||||
z2 = 0;
|
||||
}
|
||||
|
||||
reg->set24(REG_Z1MOD, z1);
|
||||
reg->set24(REG_Z2MOD, z2);
|
||||
|
||||
reg->set8_mask(REG_0x1E, scan_dummy, 0x0f);
|
||||
|
||||
reg->set8_mask(REG_0x67, static_cast<unsigned>(motor_profile.step_type) << REG_0x67S_STEPSEL,
|
||||
REG_0x67_STEPSEL);
|
||||
reg->set8_mask(REG_0x68, static_cast<unsigned>(fast_profile->step_type) << REG_0x68S_FSTPSEL,
|
||||
REG_0x68_FSTPSEL);
|
||||
|
||||
// steps for STOP table
|
||||
reg->set8(REG_FMOVDEC, fast_table.table.size() / step_multiplier);
|
||||
}
|
||||
|
||||
static void gl842_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg, unsigned int exposure,
|
||||
const ScanSession& session)
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
|
||||
scanner_setup_sensor(*dev, sensor, *reg);
|
||||
|
||||
dev->cmd_set->set_fe(dev, sensor, AFE_SET);
|
||||
|
||||
// enable shading
|
||||
regs_set_optical_off(dev->model->asic_type, *reg);
|
||||
if (has_flag(session.params.flags, ScanFlag::DISABLE_SHADING) ||
|
||||
has_flag(dev->model->flags, ModelFlag::DISABLE_SHADING_CALIBRATION) ||
|
||||
session.use_host_side_calib)
|
||||
{
|
||||
reg->find_reg(REG_0x01).value &= ~REG_0x01_DVDSET;
|
||||
|
||||
} else {
|
||||
reg->find_reg(REG_0x01).value |= REG_0x01_DVDSET;
|
||||
}
|
||||
|
||||
bool use_shdarea = true;
|
||||
|
||||
if (use_shdarea) {
|
||||
reg->find_reg(REG_0x01).value |= REG_0x01_SHDAREA;
|
||||
} else {
|
||||
reg->find_reg(REG_0x01).value &= ~REG_0x01_SHDAREA;
|
||||
}
|
||||
|
||||
if (dev->model->model_id == ModelId::CANON_8600F) {
|
||||
reg->find_reg(REG_0x03).value |= REG_0x03_AVEENB;
|
||||
} else {
|
||||
reg->find_reg(REG_0x03).value &= ~REG_0x03_AVEENB;
|
||||
}
|
||||
|
||||
// FIXME: we probably don't need to set exposure to registers at this point. It was this way
|
||||
// before a refactor.
|
||||
sanei_genesys_set_lamp_power(dev, sensor, *reg,
|
||||
!has_flag(session.params.flags, ScanFlag::DISABLE_LAMP));
|
||||
|
||||
// select XPA
|
||||
reg->find_reg(REG_0x03).value &= ~REG_0x03_XPASEL;
|
||||
if (has_flag(session.params.flags, ScanFlag::USE_XPA)) {
|
||||
reg->find_reg(REG_0x03).value |= REG_0x03_XPASEL;
|
||||
}
|
||||
reg->state.is_xpa_on = has_flag(session.params.flags, ScanFlag::USE_XPA);
|
||||
|
||||
// BW threshold
|
||||
reg->set8(REG_0x2E, 0x7f);
|
||||
reg->set8(REG_0x2F, 0x7f);
|
||||
|
||||
// monochrome / color scan parameters
|
||||
std::uint8_t reg04 = reg->get8(REG_0x04);
|
||||
reg04 = reg04 & REG_0x04_FESET;
|
||||
|
||||
switch (session.params.depth) {
|
||||
case 8:
|
||||
break;
|
||||
case 16:
|
||||
reg04 |= REG_0x04_BITSET;
|
||||
break;
|
||||
}
|
||||
|
||||
if (session.params.channels == 1) {
|
||||
switch (session.params.color_filter) {
|
||||
case ColorFilter::RED: reg04 |= 0x14; break;
|
||||
case ColorFilter::BLUE: reg04 |= 0x1c; break;
|
||||
case ColorFilter::GREEN: reg04 |= 0x18; break;
|
||||
default:
|
||||
break; // should not happen
|
||||
}
|
||||
} else {
|
||||
switch (dev->frontend.layout.type) {
|
||||
case FrontendType::WOLFSON:
|
||||
// pixel by pixel
|
||||
reg04 |= 0x10;
|
||||
break;
|
||||
case FrontendType::ANALOG_DEVICES:
|
||||
// slow color pixel by pixel
|
||||
reg04 |= 0x20;
|
||||
break;
|
||||
default:
|
||||
throw SaneException("Invalid frontend type %d",
|
||||
static_cast<unsigned>(dev->frontend.layout.type));
|
||||
}
|
||||
}
|
||||
|
||||
reg->set8(REG_0x04, reg04);
|
||||
|
||||
const auto& dpihw_sensor = sanei_genesys_find_sensor(dev, session.output_resolution,
|
||||
session.params.channels,
|
||||
session.params.scan_method);
|
||||
sanei_genesys_set_dpihw(*reg, dpihw_sensor.register_dpihw);
|
||||
|
||||
if (should_enable_gamma(session, sensor)) {
|
||||
reg->find_reg(REG_0x05).value |= REG_0x05_GMMENB;
|
||||
} else {
|
||||
reg->find_reg(REG_0x05).value &= ~REG_0x05_GMMENB;
|
||||
}
|
||||
|
||||
reg->set16(REG_DPISET, sensor.register_dpiset);
|
||||
|
||||
reg->set16(REG_STRPIXEL, session.pixel_startx);
|
||||
reg->set16(REG_ENDPIXEL, session.pixel_endx);
|
||||
|
||||
reg->set24(REG_MAXWD, session.output_line_bytes_raw);
|
||||
|
||||
unsigned tgtime = exposure / 65536 + 1;
|
||||
reg->set16(REG_LPERIOD, exposure / tgtime);
|
||||
|
||||
reg->set8(REG_DUMMY, sensor.dummy_pixel);
|
||||
}
|
||||
|
||||
void CommandSetGl842::init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg,
|
||||
const ScanSession& session) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
session.assert_computed();
|
||||
|
||||
// we enable true gray for cis scanners only, and just when doing scan since color calibration
|
||||
// is OK for this mode
|
||||
|
||||
int dummy = 0;
|
||||
|
||||
/* slope_dpi */
|
||||
/* cis color scan is effectively a gray scan with 3 gray lines per color line and a FILTER of 0 */
|
||||
int slope_dpi = 0;
|
||||
if (dev->model->is_cis) {
|
||||
slope_dpi = session.params.yres * session.params.channels;
|
||||
} else {
|
||||
slope_dpi = session.params.yres;
|
||||
}
|
||||
slope_dpi = slope_dpi * (1 + dummy);
|
||||
|
||||
int exposure = sensor.exposure_lperiod;
|
||||
if (exposure < 0) {
|
||||
throw std::runtime_error("Exposure not defined in sensor definition");
|
||||
}
|
||||
const auto& motor_profile = get_motor_profile(dev->motor.profiles, exposure, session);
|
||||
|
||||
// now _LOGICAL_ optical values used are known, setup registers
|
||||
gl842_init_optical_regs_scan(dev, sensor, reg, exposure, session);
|
||||
gl842_init_motor_regs_scan(dev, sensor, session, reg, motor_profile, exposure, slope_dpi,
|
||||
session.optical_line_count, dummy, session.params.starty,
|
||||
session.params.flags);
|
||||
|
||||
setup_image_pipeline(*dev, session);
|
||||
|
||||
dev->read_active = true;
|
||||
|
||||
dev->session = session;
|
||||
|
||||
dev->total_bytes_read = 0;
|
||||
dev->total_bytes_to_read = session.output_line_bytes_requested * session.params.lines;
|
||||
}
|
||||
|
||||
ScanSession CommandSetGl842::calculate_scan_session(const Genesys_Device* dev,
|
||||
const Genesys_Sensor& sensor,
|
||||
const Genesys_Settings& settings) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
debug_dump(DBG_info, settings);
|
||||
|
||||
ScanFlag flags = ScanFlag::NONE;
|
||||
|
||||
float move = 0.0f;
|
||||
if (settings.scan_method == ScanMethod::TRANSPARENCY ||
|
||||
settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
|
||||
{
|
||||
// note: scanner_move_to_ta() function has already been called and the sensor is at the
|
||||
// transparency adapter
|
||||
if (!dev->ignore_offsets) {
|
||||
move = dev->model->y_offset_ta - dev->model->y_offset_sensor_to_ta;
|
||||
}
|
||||
flags |= ScanFlag::USE_XPA;
|
||||
} else {
|
||||
if (!dev->ignore_offsets) {
|
||||
move = dev->model->y_offset;
|
||||
}
|
||||
}
|
||||
|
||||
move += settings.tl_y;
|
||||
|
||||
int move_dpi = dev->motor.base_ydpi;
|
||||
move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
|
||||
|
||||
float start = 0.0f;
|
||||
if (settings.scan_method==ScanMethod::TRANSPARENCY ||
|
||||
settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
|
||||
{
|
||||
start = dev->model->x_offset_ta;
|
||||
} else {
|
||||
start = dev->model->x_offset;
|
||||
}
|
||||
start = start + settings.tl_x;
|
||||
|
||||
start = static_cast<float>((start * settings.xres) / MM_PER_INCH);
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = settings.xres;
|
||||
session.params.yres = settings.yres;
|
||||
session.params.startx = static_cast<unsigned>(start);
|
||||
session.params.starty = static_cast<unsigned>(move);
|
||||
session.params.pixels = settings.pixels;
|
||||
session.params.requested_pixels = settings.requested_pixels;
|
||||
session.params.lines = settings.lines;
|
||||
session.params.depth = settings.depth;
|
||||
session.params.channels = settings.get_channels();
|
||||
session.params.scan_method = settings.scan_method;
|
||||
session.params.scan_mode = settings.scan_mode;
|
||||
session.params.color_filter = settings.color_filter;
|
||||
session.params.flags = flags;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
void CommandSetGl842::save_power(Genesys_Device* dev, bool enable) const
|
||||
{
|
||||
(void) dev;
|
||||
DBG_HELPER_ARGS(dbg, "enable = %d", enable);
|
||||
}
|
||||
|
||||
void CommandSetGl842::set_powersaving(Genesys_Device* dev, int delay /* in minutes */) const
|
||||
{
|
||||
(void) dev;
|
||||
DBG_HELPER_ARGS(dbg, "delay = %d", delay);
|
||||
}
|
||||
|
||||
void CommandSetGl842::eject_document(Genesys_Device* dev) const
|
||||
{
|
||||
(void) dev;
|
||||
DBG_HELPER(dbg);
|
||||
}
|
||||
|
||||
|
||||
void CommandSetGl842::load_document(Genesys_Device* dev) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
(void) dev;
|
||||
}
|
||||
|
||||
void CommandSetGl842::detect_document_end(Genesys_Device* dev) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
(void) dev;
|
||||
throw SaneException(SANE_STATUS_UNSUPPORTED);
|
||||
}
|
||||
|
||||
// Send the low-level scan command
|
||||
void CommandSetGl842::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg, bool start_motor) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
(void) sensor;
|
||||
|
||||
if (reg->state.is_xpa_on && reg->state.is_lamp_on &&
|
||||
!has_flag(dev->model->flags, ModelFlag::TA_NO_SECONDARY_LAMP))
|
||||
{
|
||||
dev->cmd_set->set_xpa_lamp_power(*dev, true);
|
||||
}
|
||||
if (reg->state.is_xpa_on && !has_flag(dev->model->flags, ModelFlag::UTA_NO_SECONDARY_MOTOR)) {
|
||||
dev->cmd_set->set_motor_mode(*dev, *reg, MotorMode::PRIMARY_AND_SECONDARY);
|
||||
}
|
||||
|
||||
scanner_clear_scan_and_feed_counts(*dev);
|
||||
|
||||
// enable scan and motor
|
||||
std::uint8_t val = dev->interface->read_register(REG_0x01);
|
||||
val |= REG_0x01_SCAN;
|
||||
dev->interface->write_register(REG_0x01, val);
|
||||
|
||||
scanner_start_action(*dev, start_motor);
|
||||
|
||||
switch (reg->state.motor_mode) {
|
||||
case MotorMode::PRIMARY: {
|
||||
if (reg->state.is_motor_on) {
|
||||
dev->advance_head_pos_by_session(ScanHeadId::PRIMARY);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MotorMode::PRIMARY_AND_SECONDARY: {
|
||||
if (reg->state.is_motor_on) {
|
||||
dev->advance_head_pos_by_session(ScanHeadId::PRIMARY);
|
||||
dev->advance_head_pos_by_session(ScanHeadId::SECONDARY);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MotorMode::SECONDARY: {
|
||||
if (reg->state.is_motor_on) {
|
||||
dev->advance_head_pos_by_session(ScanHeadId::SECONDARY);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CommandSetGl842::end_scan(Genesys_Device* dev, Genesys_Register_Set* reg,
|
||||
bool check_stop) const
|
||||
{
|
||||
DBG_HELPER_ARGS(dbg, "check_stop = %d", check_stop);
|
||||
|
||||
if (reg->state.is_xpa_on) {
|
||||
dev->cmd_set->set_xpa_lamp_power(*dev, false);
|
||||
}
|
||||
|
||||
if (!dev->model->is_sheetfed) {
|
||||
scanner_stop_action(*dev);
|
||||
}
|
||||
}
|
||||
|
||||
void CommandSetGl842::move_back_home(Genesys_Device* dev, bool wait_until_home) const
|
||||
{
|
||||
scanner_move_back_home(*dev, wait_until_home);
|
||||
}
|
||||
|
||||
void CommandSetGl842::init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
int move;
|
||||
|
||||
float calib_size_mm = 0;
|
||||
if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
|
||||
dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
|
||||
{
|
||||
calib_size_mm = dev->model->y_size_calib_ta_mm;
|
||||
} else {
|
||||
calib_size_mm = dev->model->y_size_calib_mm;
|
||||
}
|
||||
|
||||
unsigned resolution = sensor.shading_resolution;
|
||||
|
||||
unsigned channels = 3;
|
||||
const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
|
||||
dev->settings.scan_method);
|
||||
|
||||
unsigned calib_pixels = 0;
|
||||
unsigned calib_pixels_offset = 0;
|
||||
|
||||
if (should_calibrate_only_active_area(*dev, dev->settings)) {
|
||||
float offset = dev->model->x_offset_ta;
|
||||
// FIXME: we should use resolution here
|
||||
offset = static_cast<float>((offset * dev->settings.xres) / MM_PER_INCH);
|
||||
|
||||
float size = dev->model->x_size_ta;
|
||||
size = static_cast<float>((size * dev->settings.xres) / MM_PER_INCH);
|
||||
|
||||
calib_pixels_offset = static_cast<std::size_t>(offset);
|
||||
calib_pixels = static_cast<std::size_t>(size);
|
||||
} else {
|
||||
calib_pixels_offset = 0;
|
||||
calib_pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
|
||||
}
|
||||
|
||||
ScanFlag flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::DISABLE_BUFFER_FULL_MOVE;
|
||||
|
||||
if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
|
||||
dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
|
||||
{
|
||||
// note: scanner_move_to_ta() function has already been called and the sensor is at the
|
||||
// transparency adapter
|
||||
move = static_cast<int>(dev->model->y_offset_calib_white_ta -
|
||||
dev->model->y_offset_sensor_to_ta);
|
||||
flags |= ScanFlag::USE_XPA;
|
||||
} else {
|
||||
move = static_cast<int>(dev->model->y_offset_calib_white);
|
||||
}
|
||||
|
||||
move = static_cast<int>((move * resolution) / MM_PER_INCH);
|
||||
unsigned calib_lines = static_cast<unsigned>(calib_size_mm * resolution / MM_PER_INCH);
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = resolution;
|
||||
session.params.yres = resolution;
|
||||
session.params.startx = calib_pixels_offset;
|
||||
session.params.starty = move;
|
||||
session.params.pixels = calib_pixels;
|
||||
session.params.lines = calib_lines;
|
||||
session.params.depth = 16;
|
||||
session.params.channels = channels;
|
||||
session.params.scan_method = dev->settings.scan_method;
|
||||
session.params.scan_mode = dev->settings.scan_mode;
|
||||
session.params.color_filter = dev->settings.color_filter;
|
||||
session.params.flags = flags;
|
||||
compute_session(dev, session, calib_sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, calib_sensor, ®s, session);
|
||||
|
||||
dev->calib_session = session;
|
||||
}
|
||||
|
||||
void CommandSetGl842::send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
|
||||
if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200)
|
||||
return; // No gamma on this model
|
||||
|
||||
unsigned size = 256;
|
||||
|
||||
std::vector<uint8_t> gamma(size * 2 * 3);
|
||||
|
||||
std::vector<uint16_t> rgamma = get_gamma_table(dev, sensor, GENESYS_RED);
|
||||
std::vector<uint16_t> ggamma = get_gamma_table(dev, sensor, GENESYS_GREEN);
|
||||
std::vector<uint16_t> bgamma = get_gamma_table(dev, sensor, GENESYS_BLUE);
|
||||
|
||||
// copy sensor specific's gamma tables
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
gamma[i * 2 + size * 0 + 0] = rgamma[i] & 0xff;
|
||||
gamma[i * 2 + size * 0 + 1] = (rgamma[i] >> 8) & 0xff;
|
||||
gamma[i * 2 + size * 2 + 0] = ggamma[i] & 0xff;
|
||||
gamma[i * 2 + size * 2 + 1] = (ggamma[i] >> 8) & 0xff;
|
||||
gamma[i * 2 + size * 4 + 0] = bgamma[i] & 0xff;
|
||||
gamma[i * 2 + size * 4 + 1] = (bgamma[i] >> 8) & 0xff;
|
||||
}
|
||||
|
||||
dev->interface->write_gamma(0x28, 0x0000, gamma.data(), size * 2 * 3);
|
||||
}
|
||||
|
||||
SensorExposure CommandSetGl842::led_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const
|
||||
{
|
||||
return scanner_led_calibration(*dev, sensor, regs);
|
||||
}
|
||||
|
||||
void CommandSetGl842::offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const
|
||||
{
|
||||
scanner_offset_calibration(*dev, sensor, regs);
|
||||
}
|
||||
|
||||
void CommandSetGl842::coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs, int dpi) const
|
||||
{
|
||||
scanner_coarse_gain_calibration(*dev, sensor, regs, dpi);
|
||||
}
|
||||
|
||||
void CommandSetGl842::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
(void) sensor;
|
||||
|
||||
unsigned channels = 3;
|
||||
unsigned resolution = dev->model->get_resolution_settings(dev->settings.scan_method)
|
||||
.get_nearest_resolution_x(600);
|
||||
|
||||
const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
|
||||
dev->settings.scan_method);
|
||||
unsigned num_pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH / 2;
|
||||
|
||||
*reg = dev->reg;
|
||||
|
||||
auto flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::SINGLE_LINE |
|
||||
ScanFlag::IGNORE_STAGGER_OFFSET |
|
||||
ScanFlag::IGNORE_COLOR_OFFSET;
|
||||
if (dev->settings.scan_method == ScanMethod::TRANSPARENCY ||
|
||||
dev->settings.scan_method == ScanMethod::TRANSPARENCY_INFRARED)
|
||||
{
|
||||
flags |= ScanFlag::USE_XPA;
|
||||
}
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = resolution;
|
||||
session.params.yres = resolution;
|
||||
session.params.startx = (num_pixels / 2) * resolution / calib_sensor.full_resolution;
|
||||
session.params.starty = 0;
|
||||
session.params.pixels = num_pixels;
|
||||
session.params.lines = 1;
|
||||
session.params.depth = dev->model->bpp_color_values.front();
|
||||
session.params.channels = channels;
|
||||
session.params.scan_method = dev->settings.scan_method;
|
||||
session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
|
||||
session.params.color_filter = dev->settings.color_filter;
|
||||
session.params.flags = flags;
|
||||
|
||||
compute_session(dev, session, calib_sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, calib_sensor, reg, session);
|
||||
|
||||
sanei_genesys_set_motor_power(*reg, false);
|
||||
}
|
||||
|
||||
static void gl842_init_gpio(Genesys_Device* dev)
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
apply_registers_ordered(dev->gpo.regs, { 0x6e, 0x6f }, [&](const GenesysRegisterSetting& reg)
|
||||
{
|
||||
dev->interface->write_register(reg.address, reg.value);
|
||||
});
|
||||
}
|
||||
|
||||
void CommandSetGl842::asic_boot(Genesys_Device* dev, bool cold) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
|
||||
if (cold) {
|
||||
dev->interface->write_register(0x0e, 0x01);
|
||||
dev->interface->write_register(0x0e, 0x00);
|
||||
}
|
||||
|
||||
// setup initial register values
|
||||
gl842_init_registers(*dev);
|
||||
dev->interface->write_registers(dev->reg);
|
||||
|
||||
if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) {
|
||||
uint8_t data[32] = {
|
||||
0xd0, 0x38, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x6a, 0x73, 0x63, 0x68, 0x69, 0x65, 0x6e, 0x00,
|
||||
};
|
||||
|
||||
dev->interface->write_buffer(0x3c, 0x010a00, data, 32);
|
||||
}
|
||||
|
||||
if (dev->model->model_id == ModelId::PLUSTEK_OPTICFILM_7200) {
|
||||
dev->interface->write_0x8c(0x10, 0x94);
|
||||
}
|
||||
|
||||
// set RAM read address
|
||||
dev->interface->write_register(REG_0x2A, 0x00);
|
||||
dev->interface->write_register(REG_0x2B, 0x00);
|
||||
|
||||
// setup gpio
|
||||
gl842_init_gpio(dev);
|
||||
dev->interface->sleep_ms(100);
|
||||
}
|
||||
|
||||
void CommandSetGl842::init(Genesys_Device* dev) const
|
||||
{
|
||||
DBG_INIT();
|
||||
DBG_HELPER(dbg);
|
||||
|
||||
sanei_genesys_asic_init(dev);
|
||||
}
|
||||
|
||||
void CommandSetGl842::update_hardware_sensors(Genesys_Scanner* s) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
(void) s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send shading calibration data. The buffer is considered to always hold values
|
||||
* for all the channels.
|
||||
*/
|
||||
void CommandSetGl842::send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
uint8_t* data, int size) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
|
||||
int offset = 0;
|
||||
unsigned length = size;
|
||||
|
||||
if (dev->reg.get8(REG_0x01) & REG_0x01_SHDAREA) {
|
||||
offset = dev->session.params.startx * sensor.shading_resolution /
|
||||
dev->session.params.xres;
|
||||
|
||||
length = dev->session.output_pixels * sensor.shading_resolution /
|
||||
dev->session.params.xres;
|
||||
|
||||
offset += sensor.shading_pixel_offset;
|
||||
|
||||
// 16 bit words, 2 words per color, 3 color channels
|
||||
length *= 2 * 2 * 3;
|
||||
offset *= 2 * 2 * 3;
|
||||
} else {
|
||||
offset += sensor.shading_pixel_offset * 2 * 2 * 3;
|
||||
}
|
||||
|
||||
dev->interface->record_key_value("shading_offset", std::to_string(offset));
|
||||
dev->interface->record_key_value("shading_length", std::to_string(length));
|
||||
|
||||
std::vector<uint8_t> final_data(length, 0);
|
||||
|
||||
unsigned count = 0;
|
||||
if (offset < 0) {
|
||||
count += (-offset);
|
||||
length -= (-offset);
|
||||
offset = 0;
|
||||
}
|
||||
if (static_cast<int>(length) + offset > static_cast<int>(size)) {
|
||||
length = size - offset;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < length; i++) {
|
||||
final_data[count++] = data[offset + i];
|
||||
count++;
|
||||
}
|
||||
|
||||
dev->interface->write_buffer(0x3c, 0, final_data.data(), count);
|
||||
}
|
||||
|
||||
bool CommandSetGl842::needs_home_before_init_regs_for_scan(Genesys_Device* dev) const
|
||||
{
|
||||
(void) dev;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CommandSetGl842::wait_for_motor_stop(Genesys_Device* dev) const
|
||||
{
|
||||
(void) dev;
|
||||
}
|
||||
|
||||
} // namespace gl842
|
||||
} // namespace genesys
|
|
@ -0,0 +1,126 @@
|
|||
/* 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_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 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
|
@ -60,15 +60,11 @@ 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;
|
||||
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;
|
||||
|
@ -105,8 +101,6 @@ public:
|
|||
|
||||
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;
|
||||
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -50,81 +50,6 @@
|
|||
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 CommandSetCommon
|
||||
{
|
||||
public:
|
||||
|
@ -135,15 +60,11 @@ 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;
|
||||
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;
|
||||
|
@ -184,8 +105,6 @@ public:
|
|||
|
||||
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;
|
||||
|
||||
|
|
|
@ -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
|
@ -50,69 +50,6 @@
|
|||
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 CommandSetCommon
|
||||
{
|
||||
public:
|
||||
|
@ -123,15 +60,11 @@ 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;
|
||||
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;
|
||||
|
@ -172,8 +105,6 @@ public:
|
|||
|
||||
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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -45,6 +45,10 @@
|
|||
|
||||
#include "image.h"
|
||||
|
||||
#if defined(HAVE_TIFFIO_H)
|
||||
#include <tiffio.h>
|
||||
#endif
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace genesys {
|
||||
|
@ -201,4 +205,68 @@ void convert_pixel_row_format(const std::uint8_t* in_data, PixelFormat in_format
|
|||
}
|
||||
}
|
||||
|
||||
void write_tiff_file(const std::string& filename, const void* data, int depth, int channels,
|
||||
int pixels_per_line, int lines)
|
||||
{
|
||||
DBG_HELPER_ARGS(dbg, "depth=%d, channels=%d, ppl=%d, lines=%d", depth, channels,
|
||||
pixels_per_line, lines);
|
||||
#if defined(HAVE_TIFFIO_H)
|
||||
auto image = TIFFOpen(filename.c_str(), "w");
|
||||
if (!image) {
|
||||
dbg.log(DBG_error, "Could not save debug image");
|
||||
return;
|
||||
}
|
||||
TIFFSetField(image, TIFFTAG_IMAGEWIDTH, pixels_per_line);
|
||||
TIFFSetField(image, TIFFTAG_IMAGELENGTH, lines);
|
||||
TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, depth);
|
||||
TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, channels);
|
||||
if (channels > 1) {
|
||||
TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
|
||||
} else {
|
||||
TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
|
||||
}
|
||||
TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
TIFFSetField(image, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
|
||||
|
||||
std::size_t bytes_per_line = (pixels_per_line * channels * depth + 7) / 8;
|
||||
const std::uint8_t* data_ptr = reinterpret_cast<const std::uint8_t*>(data);
|
||||
|
||||
// we don't need to handle endian because libtiff will handle that
|
||||
for (int iline = 0; iline < lines; ++iline) {
|
||||
const auto* line_data = data_ptr + bytes_per_line * iline;
|
||||
TIFFWriteScanline(image, const_cast<std::uint8_t*>(line_data), iline, 0);
|
||||
}
|
||||
TIFFClose(image);
|
||||
|
||||
#else
|
||||
dbg.log(DBG_error, "Backend has been built without TIFF library support. "
|
||||
"Debug images will not be saved");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool is_supported_write_tiff_file_image_format(PixelFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::I1:
|
||||
case PixelFormat::RGB111:
|
||||
case PixelFormat::I8:
|
||||
case PixelFormat::RGB888:
|
||||
case PixelFormat::I16:
|
||||
case PixelFormat::RGB161616:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void write_tiff_file(const std::string& filename, const Image& image)
|
||||
{
|
||||
if (!is_supported_write_tiff_file_image_format(image.get_format())) {
|
||||
throw SaneException("Unsupported format %d", static_cast<unsigned>(image.get_format()));
|
||||
}
|
||||
|
||||
write_tiff_file(filename, image.get_row_ptr(0), get_pixel_format_depth(image.get_format()),
|
||||
get_pixel_channels(image.get_format()), image.get_width(), image.get_height());
|
||||
}
|
||||
|
||||
} // namespace genesys
|
||||
|
|
|
@ -82,6 +82,11 @@ private:
|
|||
void convert_pixel_row_format(const std::uint8_t* in_data, PixelFormat in_format,
|
||||
std::uint8_t* out_data, PixelFormat out_format, std::size_t count);
|
||||
|
||||
void write_tiff_file(const std::string& filename, const void* data, int depth,
|
||||
int channels, int pixels_per_line, int lines);
|
||||
|
||||
void write_tiff_file(const std::string& filename, const Image& image);
|
||||
|
||||
} // namespace genesys
|
||||
|
||||
#endif // ifndef BACKEND_GENESYS_IMAGE_H
|
||||
|
|
|
@ -45,13 +45,13 @@
|
|||
|
||||
#include "image_buffer.h"
|
||||
#include "image.h"
|
||||
#include "utilities.h"
|
||||
|
||||
namespace genesys {
|
||||
|
||||
ImageBuffer::ImageBuffer(std::size_t size, ProducerCallback producer) :
|
||||
producer_{producer},
|
||||
size_{size},
|
||||
buffer_offset_{size}
|
||||
size_{size}
|
||||
{
|
||||
buffer_.resize(size_);
|
||||
}
|
||||
|
@ -81,85 +81,30 @@ bool ImageBuffer::get_data(std::size_t size, std::uint8_t* out_data)
|
|||
bool got_data = true;
|
||||
do {
|
||||
buffer_offset_ = 0;
|
||||
got_data &= producer_(size_, buffer_.data());
|
||||
|
||||
std::size_t size_to_read = size_;
|
||||
if (remaining_size_ != BUFFER_SIZE_UNSET) {
|
||||
size_to_read = std::min<std::uint64_t>(size_to_read, remaining_size_);
|
||||
remaining_size_ -= size_to_read;
|
||||
}
|
||||
|
||||
std::size_t aligned_size_to_read = size_to_read;
|
||||
if (remaining_size_ == 0 && last_read_multiple_ != BUFFER_SIZE_UNSET) {
|
||||
aligned_size_to_read = align_multiple_ceil(size_to_read, last_read_multiple_);
|
||||
}
|
||||
|
||||
got_data &= producer_(aligned_size_to_read, buffer_.data());
|
||||
curr_size_ = size_to_read;
|
||||
|
||||
copy_buffer();
|
||||
} while(out_data < out_data_end && got_data);
|
||||
|
||||
if (remaining_size_ == 0 && out_data < out_data_end) {
|
||||
got_data = false;
|
||||
}
|
||||
|
||||
} while (out_data < out_data_end && got_data);
|
||||
|
||||
return got_data;
|
||||
}
|
||||
|
||||
ImageBufferGenesysUsb::ImageBufferGenesysUsb(std::size_t total_size,
|
||||
std::size_t buffer_size,
|
||||
ProducerCallback producer) :
|
||||
remaining_size_{total_size},
|
||||
buffer_size_{buffer_size},
|
||||
producer_{producer}
|
||||
{}
|
||||
|
||||
bool ImageBufferGenesysUsb::get_data(std::size_t size, std::uint8_t* out_data)
|
||||
{
|
||||
const std::uint8_t* out_data_end = out_data + size;
|
||||
|
||||
auto copy_buffer = [&]()
|
||||
{
|
||||
std::size_t bytes_copy = std::min<std::size_t>(out_data_end - out_data, available());
|
||||
std::memcpy(out_data, buffer_.data() + buffer_offset_, bytes_copy);
|
||||
out_data += bytes_copy;
|
||||
buffer_offset_ += bytes_copy;
|
||||
};
|
||||
|
||||
// first, read remaining data from buffer
|
||||
if (available() > 0) {
|
||||
copy_buffer();
|
||||
}
|
||||
|
||||
if (out_data == out_data_end) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// now the buffer is empty and there's more data to be read
|
||||
do {
|
||||
if (remaining_size_ == 0)
|
||||
return false;
|
||||
|
||||
auto bytes_to_read = get_read_size();
|
||||
buffer_offset_ = 0;
|
||||
buffer_end_ = bytes_to_read;
|
||||
buffer_.resize(bytes_to_read);
|
||||
|
||||
producer_(bytes_to_read, buffer_.data());
|
||||
|
||||
if (remaining_size_ < bytes_to_read) {
|
||||
remaining_size_ = 0;
|
||||
} else {
|
||||
remaining_size_ -= bytes_to_read;
|
||||
}
|
||||
|
||||
copy_buffer();
|
||||
} while(out_data < out_data_end);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::size_t ImageBufferGenesysUsb::get_read_size()
|
||||
{
|
||||
std::size_t size = buffer_size_;
|
||||
|
||||
// never read an odd number. exception: last read
|
||||
// the chip internal counter does not count half words.
|
||||
size &= ~1;
|
||||
|
||||
// Some setups need the reads to be multiples of 256 bytes
|
||||
size &= ~0xff;
|
||||
|
||||
if (remaining_size_ < size) {
|
||||
size = remaining_size_;
|
||||
/*round up to a multiple of 256 bytes */
|
||||
size += (size & 0xff) ? 0x100 : 0x00;
|
||||
size &= ~0xff;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
} // namespace genesys
|
||||
|
|
|
@ -56,57 +56,35 @@ class ImageBuffer
|
|||
{
|
||||
public:
|
||||
using ProducerCallback = std::function<bool(std::size_t size, std::uint8_t* out_data)>;
|
||||
static constexpr std::uint64_t BUFFER_SIZE_UNSET = std::numeric_limits<std::uint64_t>::max();
|
||||
|
||||
ImageBuffer() {}
|
||||
ImageBuffer(std::size_t size, ProducerCallback producer);
|
||||
|
||||
std::size_t size() const { return size_; }
|
||||
std::size_t available() const { return size_ - buffer_offset_; }
|
||||
std::size_t available() const { return curr_size_ - buffer_offset_; }
|
||||
|
||||
// allows adjusting the amount of data left so that we don't do a full size read from the
|
||||
// producer on the last iteration. Set to BUFFER_SIZE_UNSET to ignore buffer size.
|
||||
std::uint64_t remaining_size() const { return remaining_size_; }
|
||||
void set_remaining_size(std::uint64_t bytes) { remaining_size_ = bytes; }
|
||||
|
||||
// May be used to force the last read to be rounded up of a certain number of bytes
|
||||
void set_last_read_multiple(std::uint64_t bytes) { last_read_multiple_ = bytes; }
|
||||
|
||||
bool get_data(std::size_t size, std::uint8_t* out_data);
|
||||
|
||||
private:
|
||||
ProducerCallback producer_;
|
||||
std::size_t size_ = 0;
|
||||
std::size_t curr_size_ = 0;
|
||||
|
||||
std::uint64_t remaining_size_ = BUFFER_SIZE_UNSET;
|
||||
std::uint64_t last_read_multiple_ = BUFFER_SIZE_UNSET;
|
||||
|
||||
std::size_t buffer_offset_ = 0;
|
||||
std::vector<std::uint8_t> buffer_;
|
||||
};
|
||||
|
||||
// This class is similar to ImageBuffer, but preserves historical peculiarities of buffer handling
|
||||
// in the backend to preserve exact behavior
|
||||
class ImageBufferGenesysUsb
|
||||
{
|
||||
public:
|
||||
using ProducerCallback = std::function<void(std::size_t size, std::uint8_t* out_data)>;
|
||||
|
||||
ImageBufferGenesysUsb() {}
|
||||
ImageBufferGenesysUsb(std::size_t total_size, std::size_t buffer_size,
|
||||
ProducerCallback producer);
|
||||
|
||||
std::size_t remaining_size() const { return remaining_size_; }
|
||||
|
||||
void set_remaining_size(std::size_t bytes) { remaining_size_ = bytes; }
|
||||
|
||||
std::size_t available() const { return buffer_end_ - buffer_offset_; }
|
||||
|
||||
bool get_data(std::size_t size, std::uint8_t* out_data);
|
||||
|
||||
private:
|
||||
|
||||
std::size_t get_read_size();
|
||||
|
||||
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_;
|
||||
|
||||
ProducerCallback producer_;
|
||||
};
|
||||
|
||||
} // namespace genesys
|
||||
|
||||
#endif // BACKEND_GENESYS_IMAGE_BUFFER_H
|
||||
|
|
|
@ -53,15 +53,6 @@ namespace genesys {
|
|||
|
||||
ImagePipelineNode::~ImagePipelineNode() {}
|
||||
|
||||
std::size_t ImagePipelineNodeBytesSource::consume_remaining_bytes(std::size_t bytes)
|
||||
{
|
||||
if (bytes > remaining_bytes_) {
|
||||
bytes = remaining_bytes_;
|
||||
}
|
||||
remaining_bytes_ -= bytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
bool ImagePipelineNodeCallableSource::get_next_row_data(std::uint8_t* out_data)
|
||||
{
|
||||
bool got_data = producer_(get_row_bytes(), out_data);
|
||||
|
@ -78,7 +69,7 @@ ImagePipelineNodeBufferedCallableSource::ImagePipelineNodeBufferedCallableSource
|
|||
format_{format},
|
||||
buffer_{input_batch_size, producer}
|
||||
{
|
||||
set_remaining_bytes(height_ * get_row_bytes());
|
||||
buffer_.set_remaining_size(height_ * get_row_bytes());
|
||||
}
|
||||
|
||||
bool ImagePipelineNodeBufferedCallableSource::get_next_row_data(std::uint8_t* out_data)
|
||||
|
@ -92,13 +83,7 @@ bool ImagePipelineNodeBufferedCallableSource::get_next_row_data(std::uint8_t* ou
|
|||
|
||||
bool got_data = true;
|
||||
|
||||
auto row_bytes = get_row_bytes();
|
||||
auto bytes_to_ask = consume_remaining_bytes(row_bytes);
|
||||
if (bytes_to_ask < row_bytes) {
|
||||
got_data = false;
|
||||
}
|
||||
|
||||
got_data &= buffer_.get_data(bytes_to_ask, out_data);
|
||||
got_data &= buffer_.get_data(get_row_bytes(), out_data);
|
||||
curr_row_++;
|
||||
if (!got_data) {
|
||||
eof_ = true;
|
||||
|
@ -106,37 +91,6 @@ bool ImagePipelineNodeBufferedCallableSource::get_next_row_data(std::uint8_t* ou
|
|||
return got_data;
|
||||
}
|
||||
|
||||
|
||||
ImagePipelineNodeBufferedGenesysUsb::ImagePipelineNodeBufferedGenesysUsb(
|
||||
std::size_t width, std::size_t height, PixelFormat format, std::size_t total_size,
|
||||
std::size_t buffer_size, ProducerCallback producer) :
|
||||
width_{width},
|
||||
height_{height},
|
||||
format_{format},
|
||||
buffer_{total_size, buffer_size, producer}
|
||||
{
|
||||
set_remaining_bytes(total_size);
|
||||
}
|
||||
|
||||
bool ImagePipelineNodeBufferedGenesysUsb::get_next_row_data(std::uint8_t* out_data)
|
||||
{
|
||||
if (remaining_bytes() != buffer_.remaining_size() + buffer_.available()) {
|
||||
buffer_.set_remaining_size(remaining_bytes() - buffer_.available());
|
||||
}
|
||||
bool got_data = true;
|
||||
|
||||
std::size_t row_bytes = get_row_bytes();
|
||||
std::size_t ask_bytes = consume_remaining_bytes(row_bytes);
|
||||
if (ask_bytes < row_bytes) {
|
||||
got_data = false;
|
||||
}
|
||||
got_data &= buffer_.get_data(ask_bytes, out_data);
|
||||
if (!got_data) {
|
||||
eof_ = true;
|
||||
}
|
||||
return got_data;
|
||||
}
|
||||
|
||||
ImagePipelineNodeArraySource::ImagePipelineNodeArraySource(std::size_t width, std::size_t height,
|
||||
PixelFormat format,
|
||||
std::vector<std::uint8_t> data) :
|
||||
|
@ -151,7 +105,6 @@ ImagePipelineNodeArraySource::ImagePipelineNodeArraySource(std::size_t width, st
|
|||
throw SaneException("The given array is too small (%zu bytes). Need at least %zu",
|
||||
data_.size(), size);
|
||||
}
|
||||
set_remaining_bytes(size);
|
||||
}
|
||||
|
||||
bool ImagePipelineNodeArraySource::get_next_row_data(std::uint8_t* out_data)
|
||||
|
@ -161,21 +114,11 @@ bool ImagePipelineNodeArraySource::get_next_row_data(std::uint8_t* out_data)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool got_data = true;
|
||||
|
||||
auto row_bytes = get_row_bytes();
|
||||
auto bytes_to_ask = consume_remaining_bytes(row_bytes);
|
||||
if (bytes_to_ask < row_bytes) {
|
||||
got_data = false;
|
||||
}
|
||||
|
||||
std::memcpy(out_data, data_.data() + get_row_bytes() * next_row_, bytes_to_ask);
|
||||
std::memcpy(out_data, data_.data() + row_bytes * next_row_, row_bytes);
|
||||
next_row_++;
|
||||
|
||||
if (!got_data) {
|
||||
eof_ = true;
|
||||
}
|
||||
return got_data;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -319,6 +262,50 @@ 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;
|
||||
auto num_bytes = (num_values + 7) / 8;
|
||||
for (std::size_t i = 0; i < num_bytes; ++i) {
|
||||
*data = ~*data;
|
||||
data++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw SaneException("Unsupported pixel depth");
|
||||
}
|
||||
|
||||
return got_data;
|
||||
}
|
||||
|
||||
ImagePipelineNodeMergeMonoLines::ImagePipelineNodeMergeMonoLines(ImagePipelineNode& source,
|
||||
ColorOrder color_order) :
|
||||
source_(source),
|
||||
|
@ -456,6 +443,12 @@ ImagePipelineNodeComponentShiftLines::ImagePipelineNodeComponentShiftLines(
|
|||
static_cast<unsigned>(source.get_format()));
|
||||
}
|
||||
extra_height_ = *std::max_element(channel_shifts_.begin(), channel_shifts_.end());
|
||||
height_ = source_.get_height();
|
||||
if (extra_height_ > height_) {
|
||||
height_ = 0;
|
||||
} else {
|
||||
height_ -= extra_height_;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImagePipelineNodeComponentShiftLines::get_next_row_data(std::uint8_t* out_data)
|
||||
|
@ -492,18 +485,13 @@ ImagePipelineNodePixelShiftLines::ImagePipelineNodePixelShiftLines(
|
|||
pixel_shifts_{shifts},
|
||||
buffer_{get_row_bytes()}
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
DBG(DBG_proc, "%s: shifts={", __func__);
|
||||
for (auto el : pixel_shifts_) {
|
||||
DBG(DBG_proc, " %zu", el);
|
||||
}
|
||||
DBG(DBG_proc, " }\n");
|
||||
|
||||
if (pixel_shifts_.size() > MAX_SHIFTS) {
|
||||
throw SaneException("Unsupported number of shift configurations %zu", pixel_shifts_.size());
|
||||
}
|
||||
|
||||
extra_height_ = *std::max_element(pixel_shifts_.begin(), pixel_shifts_.end());
|
||||
height_ = source_.get_height();
|
||||
if (extra_height_ > height_) {
|
||||
height_ = 0;
|
||||
} else {
|
||||
height_ -= extra_height_;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImagePipelineNodePixelShiftLines::get_next_row_data(std::uint8_t* out_data)
|
||||
|
@ -521,7 +509,8 @@ bool ImagePipelineNodePixelShiftLines::get_next_row_data(std::uint8_t* out_data)
|
|||
auto format = get_format();
|
||||
auto shift_count = pixel_shifts_.size();
|
||||
|
||||
std::array<std::uint8_t*, MAX_SHIFTS> rows;
|
||||
std::vector<std::uint8_t*> rows;
|
||||
rows.resize(shift_count, nullptr);
|
||||
|
||||
for (std::size_t irow = 0; irow < shift_count; ++irow) {
|
||||
rows[irow] = buffer_.get_row_ptr(pixel_shifts_[irow]);
|
||||
|
@ -536,6 +525,63 @@ bool ImagePipelineNodePixelShiftLines::get_next_row_data(std::uint8_t* out_data)
|
|||
return got_data;
|
||||
}
|
||||
|
||||
ImagePipelineNodePixelShiftColumns::ImagePipelineNodePixelShiftColumns(
|
||||
ImagePipelineNode& source, const std::vector<std::size_t>& shifts) :
|
||||
source_(source),
|
||||
pixel_shifts_{shifts}
|
||||
{
|
||||
width_ = source_.get_width();
|
||||
extra_width_ = compute_pixel_shift_extra_width(width_, pixel_shifts_);
|
||||
if (extra_width_ > width_) {
|
||||
width_ = 0;
|
||||
} else {
|
||||
width_ -= extra_width_;
|
||||
}
|
||||
temp_buffer_.resize(source_.get_row_bytes());
|
||||
}
|
||||
|
||||
bool ImagePipelineNodePixelShiftColumns::get_next_row_data(std::uint8_t* out_data)
|
||||
{
|
||||
if (width_ == 0) {
|
||||
throw SaneException("Attempt to read zero-width line");
|
||||
}
|
||||
bool got_data = source_.get_next_row_data(temp_buffer_.data());
|
||||
|
||||
auto format = get_format();
|
||||
auto shift_count = pixel_shifts_.size();
|
||||
|
||||
for (std::size_t x = 0, width = get_width(); x < width; x += shift_count) {
|
||||
for (std::size_t ishift = 0; ishift < shift_count && x + ishift < width; ishift++) {
|
||||
RawPixel pixel = get_raw_pixel_from_row(temp_buffer_.data(), x + pixel_shifts_[ishift],
|
||||
format);
|
||||
set_raw_pixel_to_row(out_data, x + ishift, pixel, format);
|
||||
}
|
||||
}
|
||||
return got_data;
|
||||
}
|
||||
|
||||
|
||||
std::size_t compute_pixel_shift_extra_width(std::size_t source_width,
|
||||
const std::vector<std::size_t>& shifts)
|
||||
{
|
||||
// we iterate across pixel shifts and find the pixel that needs the maximum shift according to
|
||||
// source_width.
|
||||
int group_size = shifts.size();
|
||||
int non_filled_group = source_width % shifts.size();
|
||||
int extra_width = 0;
|
||||
|
||||
for (int i = 0; i < group_size; ++i) {
|
||||
int shift_groups = shifts[i] / group_size;
|
||||
int shift_rem = shifts[i] % group_size;
|
||||
|
||||
if (shift_rem < non_filled_group) {
|
||||
shift_groups--;
|
||||
}
|
||||
extra_width = std::max(extra_width, shift_groups * group_size + non_filled_group - i);
|
||||
}
|
||||
return extra_width;
|
||||
}
|
||||
|
||||
ImagePipelineNodeExtract::ImagePipelineNodeExtract(ImagePipelineNode& source,
|
||||
std::size_t offset_x, std::size_t offset_y,
|
||||
std::size_t width, std::size_t height) :
|
||||
|
@ -734,10 +780,8 @@ ImagePipelineNodeDebug::~ImagePipelineNodeDebug()
|
|||
|
||||
auto format = get_format();
|
||||
buffer_.linearize();
|
||||
sanei_genesys_write_pnm_file(path_.c_str(), buffer_.get_front_row_ptr(),
|
||||
get_pixel_format_depth(format),
|
||||
get_pixel_channels(format),
|
||||
get_width(), buffer_.height());
|
||||
write_tiff_file(path_, buffer_.get_front_row_ptr(), get_pixel_format_depth(format),
|
||||
get_pixel_channels(format), get_width(), buffer_.height());
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -75,18 +75,6 @@ public:
|
|||
virtual bool get_next_row_data(std::uint8_t* out_data) = 0;
|
||||
};
|
||||
|
||||
class ImagePipelineNodeBytesSource : public ImagePipelineNode
|
||||
{
|
||||
public:
|
||||
std::size_t remaining_bytes() const { return remaining_bytes_; }
|
||||
void set_remaining_bytes(std::size_t bytes) { remaining_bytes_ = bytes; }
|
||||
|
||||
std::size_t consume_remaining_bytes(std::size_t bytes);
|
||||
|
||||
private:
|
||||
std::size_t remaining_bytes_ = 0;
|
||||
};
|
||||
|
||||
// A pipeline node that produces data from a callable
|
||||
class ImagePipelineNodeCallableSource : public ImagePipelineNode
|
||||
{
|
||||
|
@ -118,7 +106,7 @@ private:
|
|||
};
|
||||
|
||||
// A pipeline node that produces data from a callable requesting fixed-size chunks.
|
||||
class ImagePipelineNodeBufferedCallableSource : public ImagePipelineNodeBytesSource
|
||||
class ImagePipelineNodeBufferedCallableSource : public ImagePipelineNode
|
||||
{
|
||||
public:
|
||||
using ProducerCallback = std::function<bool(std::size_t size, std::uint8_t* out_data)>;
|
||||
|
@ -135,8 +123,9 @@ public:
|
|||
|
||||
bool get_next_row_data(std::uint8_t* out_data) override;
|
||||
|
||||
std::size_t buffer_size() const { return buffer_.size(); }
|
||||
std::size_t buffer_available() const { return buffer_.available(); }
|
||||
std::size_t remaining_bytes() const { return buffer_.remaining_size(); }
|
||||
void set_remaining_bytes(std::size_t bytes) { buffer_.set_remaining_size(bytes); }
|
||||
void set_last_read_multiple(std::size_t bytes) { buffer_.set_last_read_multiple(bytes); }
|
||||
|
||||
private:
|
||||
ProducerCallback producer_;
|
||||
|
@ -150,38 +139,8 @@ private:
|
|||
ImageBuffer buffer_;
|
||||
};
|
||||
|
||||
class ImagePipelineNodeBufferedGenesysUsb : public ImagePipelineNodeBytesSource
|
||||
{
|
||||
public:
|
||||
using ProducerCallback = std::function<void(std::size_t size, std::uint8_t* out_data)>;
|
||||
|
||||
ImagePipelineNodeBufferedGenesysUsb(std::size_t width, std::size_t height,
|
||||
PixelFormat format, std::size_t total_size,
|
||||
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_; }
|
||||
PixelFormat get_format() const override { return format_; }
|
||||
|
||||
bool eof() const override { return eof_; }
|
||||
|
||||
bool get_next_row_data(std::uint8_t* out_data) override;
|
||||
|
||||
std::size_t buffer_available() const { return buffer_.available(); }
|
||||
|
||||
private:
|
||||
ProducerCallback producer_;
|
||||
std::size_t width_ = 0;
|
||||
std::size_t height_ = 0;
|
||||
PixelFormat format_ = PixelFormat::UNKNOWN;
|
||||
|
||||
bool eof_ = false;
|
||||
|
||||
ImageBufferGenesysUsb buffer_;
|
||||
};
|
||||
|
||||
// A pipeline node that produces data from the given array.
|
||||
class ImagePipelineNodeArraySource : public ImagePipelineNodeBytesSource
|
||||
class ImagePipelineNodeArraySource : public ImagePipelineNode
|
||||
{
|
||||
public:
|
||||
ImagePipelineNodeArraySource(std::size_t width, std::size_t height, PixelFormat format,
|
||||
|
@ -301,7 +260,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:
|
||||
|
@ -320,6 +279,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
|
||||
{
|
||||
|
@ -376,7 +352,7 @@ public:
|
|||
unsigned shift_r, unsigned shift_g, unsigned shift_b);
|
||||
|
||||
std::size_t get_width() const override { return source_.get_width(); }
|
||||
std::size_t get_height() const override { return source_.get_height() - extra_height_; }
|
||||
std::size_t get_height() const override { return height_; }
|
||||
PixelFormat get_format() const override { return source_.get_format(); }
|
||||
|
||||
bool eof() const override { return source_.eof(); }
|
||||
|
@ -386,23 +362,23 @@ public:
|
|||
private:
|
||||
ImagePipelineNode& source_;
|
||||
std::size_t extra_height_ = 0;
|
||||
std::size_t height_ = 0;
|
||||
|
||||
std::array<unsigned, 3> channel_shifts_;
|
||||
|
||||
RowBuffer buffer_;
|
||||
};
|
||||
|
||||
// A pipeline node that shifts pixels across lines by the given offsets (performs unstaggering)
|
||||
// A pipeline node that shifts pixels across lines by the given offsets (performs vertical
|
||||
// unstaggering)
|
||||
class ImagePipelineNodePixelShiftLines : public ImagePipelineNode
|
||||
{
|
||||
public:
|
||||
constexpr static std::size_t MAX_SHIFTS = 2;
|
||||
|
||||
ImagePipelineNodePixelShiftLines(ImagePipelineNode& source,
|
||||
const std::vector<std::size_t>& shifts);
|
||||
|
||||
std::size_t get_width() const override { return source_.get_width(); }
|
||||
std::size_t get_height() const override { return source_.get_height() - extra_height_; }
|
||||
std::size_t get_height() const override { return height_; }
|
||||
PixelFormat get_format() const override { return source_.get_format(); }
|
||||
|
||||
bool eof() const override { return source_.eof(); }
|
||||
|
@ -412,12 +388,44 @@ public:
|
|||
private:
|
||||
ImagePipelineNode& source_;
|
||||
std::size_t extra_height_ = 0;
|
||||
std::size_t height_ = 0;
|
||||
|
||||
std::vector<std::size_t> pixel_shifts_;
|
||||
|
||||
RowBuffer buffer_;
|
||||
};
|
||||
|
||||
// A pipeline node that shifts pixels across columns by the given offsets. Each row is divided
|
||||
// into pixel groups of shifts.size() pixels. For each output group starting at position xgroup,
|
||||
// the i-th pixel will be set to the input pixel at position xgroup + shifts[i].
|
||||
class ImagePipelineNodePixelShiftColumns : public ImagePipelineNode
|
||||
{
|
||||
public:
|
||||
ImagePipelineNodePixelShiftColumns(ImagePipelineNode& source,
|
||||
const std::vector<std::size_t>& shifts);
|
||||
|
||||
std::size_t get_width() const override { return 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_;
|
||||
std::size_t width_ = 0;
|
||||
std::size_t extra_width_ = 0;
|
||||
|
||||
std::vector<std::size_t> pixel_shifts_;
|
||||
|
||||
std::vector<std::uint8_t> temp_buffer_;
|
||||
};
|
||||
|
||||
// exposed for tests
|
||||
std::size_t compute_pixel_shift_extra_width(std::size_t source_width,
|
||||
const std::vector<std::size_t>& shifts);
|
||||
|
||||
// A pipeline node that extracts a sub-image from the image. Padding and cropping is done as needed.
|
||||
// The class can't pad to the left of the image currently, as only positive offsets are accepted.
|
||||
class ImagePipelineNodeExtract : public ImagePipelineNode
|
||||
|
@ -516,6 +524,19 @@ class ImagePipelineStack
|
|||
{
|
||||
public:
|
||||
ImagePipelineStack() {}
|
||||
ImagePipelineStack(ImagePipelineStack&& other)
|
||||
{
|
||||
clear();
|
||||
nodes_ = std::move(other.nodes_);
|
||||
}
|
||||
|
||||
ImagePipelineStack& operator=(ImagePipelineStack&& other)
|
||||
{
|
||||
clear();
|
||||
nodes_ = std::move(other.nodes_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~ImagePipelineStack() { clear(); }
|
||||
|
||||
std::size_t get_input_width() const;
|
||||
|
@ -535,20 +556,22 @@ public:
|
|||
void clear();
|
||||
|
||||
template<class Node, class... Args>
|
||||
void push_first_node(Args&&... args)
|
||||
Node& push_first_node(Args&&... args)
|
||||
{
|
||||
if (!nodes_.empty()) {
|
||||
throw SaneException("Trying to append first node when there are existing nodes");
|
||||
}
|
||||
nodes_.emplace_back(std::unique_ptr<Node>(new Node(std::forward<Args>(args)...)));
|
||||
return static_cast<Node&>(*nodes_.back());
|
||||
}
|
||||
|
||||
template<class Node, class... Args>
|
||||
void push_node(Args&&... args)
|
||||
Node& push_node(Args&&... args)
|
||||
{
|
||||
ensure_node_exists();
|
||||
nodes_.emplace_back(std::unique_ptr<Node>(new Node(*nodes_.back(),
|
||||
std::forward<Args>(args)...)));
|
||||
return static_cast<Node&>(*nodes_.back());
|
||||
}
|
||||
|
||||
bool get_next_row_data(std::uint8_t* out_data)
|
||||
|
|
|
@ -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
|
@ -153,50 +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_;
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* 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);
|
||||
|
@ -210,21 +220,26 @@ void scanner_read_print_status(Genesys_Device& dev);
|
|||
|
||||
void debug_print_status(DebugMessageHelper& dbg, Status status);
|
||||
|
||||
void scanner_register_rw_clear_bits(Genesys_Device& dev, std::uint16_t address, std::uint8_t mask);
|
||||
void scanner_register_rw_set_bits(Genesys_Device& dev, std::uint16_t address, std::uint8_t mask);
|
||||
void scanner_register_rw_bits(Genesys_Device& dev, std::uint16_t address,
|
||||
std::uint8_t value, std::uint8_t mask);
|
||||
|
||||
extern void sanei_genesys_write_ahb(Genesys_Device* dev, uint32_t addr, uint32_t size,
|
||||
uint8_t* data);
|
||||
|
||||
extern void sanei_genesys_init_structs (Genesys_Device * dev);
|
||||
|
||||
const Genesys_Sensor& sanei_genesys_find_sensor_any(Genesys_Device* dev);
|
||||
const Genesys_Sensor& sanei_genesys_find_sensor(Genesys_Device* dev, unsigned dpi,
|
||||
const Genesys_Sensor& sanei_genesys_find_sensor_any(const Genesys_Device* dev);
|
||||
const Genesys_Sensor& sanei_genesys_find_sensor(const Genesys_Device* dev, unsigned dpi,
|
||||
unsigned channels, ScanMethod scan_method);
|
||||
bool sanei_genesys_has_sensor(Genesys_Device* dev, unsigned dpi, unsigned channels,
|
||||
bool sanei_genesys_has_sensor(const Genesys_Device* dev, unsigned dpi, unsigned channels,
|
||||
ScanMethod scan_method);
|
||||
Genesys_Sensor& sanei_genesys_find_sensor_for_write(Genesys_Device* dev, unsigned dpi,
|
||||
unsigned channels, ScanMethod scan_method);
|
||||
|
||||
std::vector<std::reference_wrapper<const Genesys_Sensor>>
|
||||
sanei_genesys_find_sensors_all(Genesys_Device* dev, ScanMethod scan_method);
|
||||
sanei_genesys_find_sensors_all(const Genesys_Device* dev, ScanMethod scan_method);
|
||||
std::vector<std::reference_wrapper<Genesys_Sensor>>
|
||||
sanei_genesys_find_sensors_all_for_write(Genesys_Device* dev, ScanMethod scan_method);
|
||||
|
||||
|
@ -269,13 +284,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);
|
||||
|
||||
|
@ -303,19 +314,26 @@ void scanner_move_back_home_ta(Genesys_Device& dev);
|
|||
*/
|
||||
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);
|
||||
|
||||
extern void sanei_genesys_write_pnm_file(const char* filename, const std::uint8_t* data, int depth,
|
||||
int channels, int pixels_per_line, int lines);
|
||||
|
||||
void sanei_genesys_write_pnm_file(const char* filename, const Image& image);
|
||||
|
||||
extern void sanei_genesys_write_pnm_file16(const char* filename, const uint16_t *data, unsigned channels,
|
||||
unsigned pixels_per_line, unsigned lines);
|
||||
|
||||
void wait_until_buffer_non_empty(Genesys_Device* dev, bool check_status_twice = false);
|
||||
|
||||
extern void sanei_genesys_read_data_from_scanner(Genesys_Device* dev, uint8_t* data, size_t size);
|
||||
|
@ -328,8 +346,7 @@ 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);
|
||||
void sanei_genesys_set_dpihw(Genesys_Register_Set& regs, unsigned dpihw);
|
||||
|
||||
inline SensorExposure sanei_genesys_fixup_exposure(SensorExposure exposure)
|
||||
{
|
||||
|
@ -343,7 +360,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);
|
||||
|
@ -351,6 +368,9 @@ void scanner_stop_action_no_move(Genesys_Device& dev, Genesys_Register_Set& regs
|
|||
|
||||
bool scanner_is_motor_stopped(Genesys_Device& dev);
|
||||
|
||||
void scanner_setup_sensor(Genesys_Device& dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs);
|
||||
|
||||
const MotorProfile* get_motor_profile_ptr(const std::vector<MotorProfile>& profiles,
|
||||
unsigned exposure,
|
||||
const ScanSession& session);
|
||||
|
@ -359,9 +379,9 @@ const MotorProfile& get_motor_profile(const std::vector<MotorProfile>& profiles,
|
|||
unsigned exposure,
|
||||
const ScanSession& session);
|
||||
|
||||
MotorSlopeTable sanei_genesys_slope_table(AsicType asic_type, int dpi, int exposure, int base_dpi,
|
||||
unsigned step_multiplier,
|
||||
const MotorProfile& motor_profile);
|
||||
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 MotorProfile& motor_profile);
|
||||
|
@ -401,53 +421,22 @@ extern void sanei_genesys_generate_gamma_buffer(Genesys_Device* dev,
|
|||
int size,
|
||||
uint8_t* gamma);
|
||||
|
||||
unsigned session_adjust_output_pixels(unsigned output_pixels,
|
||||
const Genesys_Device& dev, const Genesys_Sensor& sensor,
|
||||
unsigned output_xresolution, unsigned output_yresolution,
|
||||
bool adjust_output_pixels);
|
||||
|
||||
void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Sensor& sensor);
|
||||
|
||||
void build_image_pipeline(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
const ScanSession& session);
|
||||
ImagePipelineStack build_image_pipeline(const Genesys_Device& dev, const ScanSession& session,
|
||||
unsigned pipeline_index, bool log_image_data);
|
||||
|
||||
// sets up a image pipeline for device `dev`
|
||||
void setup_image_pipeline(Genesys_Device& dev, const ScanSession& session);
|
||||
|
||||
std::uint8_t compute_frontend_gain(float value, float target_value,
|
||||
FrontendType frontend_type);
|
||||
|
||||
template<class T>
|
||||
inline T abs_diff(T a, T b)
|
||||
{
|
||||
if (a < b) {
|
||||
return b - a;
|
||||
} else {
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
|
||||
inline uint64_t align_multiple_floor(uint64_t x, uint64_t multiple)
|
||||
{
|
||||
return (x / multiple) * multiple;
|
||||
}
|
||||
|
||||
inline uint64_t align_multiple_ceil(uint64_t x, uint64_t multiple)
|
||||
{
|
||||
return ((x + multiple - 1) / multiple) * multiple;
|
||||
}
|
||||
|
||||
inline uint64_t multiply_by_depth_ceil(uint64_t pixels, uint64_t depth)
|
||||
{
|
||||
if (depth == 1) {
|
||||
return (pixels / 8) + ((pixels % 8) ? 1 : 0);
|
||||
} else {
|
||||
return pixels * (depth / 8);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T clamp(const T& value, const T& lo, const T& hi)
|
||||
{
|
||||
if (value < lo)
|
||||
return lo;
|
||||
if (value > hi)
|
||||
return hi;
|
||||
return value;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* ASIC specific functions declarations */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -455,14 +444,17 @@ 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_usb_device_tables();
|
||||
void verify_sensor_tables();
|
||||
void verify_usb_device_tables();
|
||||
|
||||
template<class T>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -180,9 +195,8 @@ std::ostream& operator<<(std::ostream& out, const MotorProfile& profile)
|
|||
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'
|
||||
<< " profiles: "
|
||||
<< format_indent_braced_list(4, format_vector_indent_braced(4, "MotorProfile",
|
||||
motor.profiles)) << '\n'
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include <vector>
|
||||
#include "enums.h"
|
||||
#include "sensor.h"
|
||||
#include "value_filter.h"
|
||||
|
||||
namespace genesys {
|
||||
|
||||
|
@ -125,17 +126,24 @@ 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);
|
||||
|
||||
|
@ -151,9 +159,9 @@ struct MotorProfile
|
|||
int motor_vref = -1;
|
||||
|
||||
// the resolutions this profile is good for
|
||||
ResolutionFilter resolutions = ResolutionFilter::ANY;
|
||||
ValueFilterAny<unsigned> resolutions = VALUE_FILTER_ANY;
|
||||
// the scan method this profile is good for. If the list is empty, good for any method.
|
||||
ScanMethodFilter scan_methods = ScanMethodFilter::ANY;
|
||||
ValueFilterAny<ScanMethod> scan_methods = VALUE_FILTER_ANY;
|
||||
|
||||
unsigned max_exposure = 0; // 0 - any exposure
|
||||
};
|
||||
|
@ -168,8 +176,6 @@ 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<MotorProfile> profiles;
|
||||
// slopes to derive individual slopes from for fast moving
|
||||
|
|
|
@ -415,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);
|
||||
|
|
|
@ -70,7 +70,6 @@ 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) = 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)
|
||||
{
|
||||
|
@ -356,6 +358,7 @@ void ScannerInterfaceUsb::write_buffer(std::uint8_t type, std::uint32_t addr, st
|
|||
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");
|
||||
|
@ -377,6 +380,7 @@ void ScannerInterfaceUsb::write_gamma(std::uint8_t type, std::uint32_t addr, std
|
|||
{
|
||||
DBG_HELPER_ARGS(dbg, "type: 0x%02x, addr: 0x%08x, size: 0x%08zx", type, addr, size);
|
||||
if (dev_->model->asic_type != AsicType::GL841 &&
|
||||
dev_->model->asic_type != AsicType::GL842 &&
|
||||
dev_->model->asic_type != AsicType::GL843)
|
||||
{
|
||||
throw SaneException("Unsupported transfer mode");
|
||||
|
@ -386,7 +390,9 @@ void ScannerInterfaceUsb::write_gamma(std::uint8_t type, std::uint32_t addr, std
|
|||
write_register(0x5c, ((addr >> 4) & 0xff));
|
||||
bulk_write_data(type, data, size);
|
||||
|
||||
if (dev_->model->asic_type == AsicType::GL843) {
|
||||
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);
|
||||
|
|
|
@ -51,10 +51,16 @@ namespace genesys {
|
|||
|
||||
std::ostream& operator<<(std::ostream& out, const StaggerConfig& config)
|
||||
{
|
||||
out << "StaggerConfig{\n"
|
||||
<< " min_resolution: " << config.min_resolution() << '\n'
|
||||
<< " lines_at_min: " << config.lines_at_min() << '\n'
|
||||
<< "}";
|
||||
if (config.shifts().empty()) {
|
||||
out << "StaggerConfig{}";
|
||||
return out;
|
||||
}
|
||||
|
||||
out << "StaggerConfig{ " << config.shifts().front();
|
||||
for (auto it = std::next(config.shifts().begin()); it != config.shifts().end(); ++it) {
|
||||
out << ", " << *it;
|
||||
}
|
||||
out << " }";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -64,6 +70,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 +102,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,42 +123,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 ScanMethodFilter& methods)
|
||||
{
|
||||
if (methods.matches_any()) {
|
||||
out << "ANY";
|
||||
return out;
|
||||
}
|
||||
out << format_vector_unsigned(4, methods.methods());
|
||||
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'
|
||||
<< " 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'
|
||||
|
@ -155,9 +147,9 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Sensor& sensor)
|
|||
<< " segment_size: " << sensor.segment_size << '\n'
|
||||
<< " 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'
|
||||
<< " stagger_x: " << sensor.stagger_x << '\n'
|
||||
<< " stagger_y: " << sensor.stagger_y << '\n'
|
||||
<< " use_host_side_calib: " << sensor.use_host_side_calib << '\n'
|
||||
<< " custom_base_regs: " << format_indent_braced_list(4, sensor.custom_base_regs) << '\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>
|
||||
|
||||
|
@ -72,31 +73,30 @@ class StaggerConfig
|
|||
{
|
||||
public:
|
||||
StaggerConfig() = default;
|
||||
StaggerConfig(unsigned min_resolution, unsigned lines_at_min) :
|
||||
min_resolution_{min_resolution},
|
||||
lines_at_min_{lines_at_min}
|
||||
explicit StaggerConfig(std::initializer_list<std::size_t> shifts) :
|
||||
shifts_{shifts}
|
||||
{
|
||||
}
|
||||
|
||||
unsigned stagger_at_resolution(unsigned xresolution, unsigned yresolution) const
|
||||
std::size_t max_shift() const
|
||||
{
|
||||
if (min_resolution_ == 0 || xresolution < min_resolution_)
|
||||
if (shifts_.empty()) {
|
||||
return 0;
|
||||
return yresolution / min_resolution_ * lines_at_min_;
|
||||
}
|
||||
return *std::max_element(shifts_.begin(), shifts_.end());
|
||||
}
|
||||
|
||||
unsigned min_resolution() const { return min_resolution_; }
|
||||
unsigned lines_at_min() const { return lines_at_min_; }
|
||||
bool empty() const { return shifts_.empty(); }
|
||||
std::size_t size() const { return shifts_.size(); }
|
||||
const std::vector<std::size_t>& shifts() const { return shifts_; }
|
||||
|
||||
bool operator==(const StaggerConfig& other) const
|
||||
{
|
||||
return min_resolution_ == other.min_resolution_ &&
|
||||
lines_at_min_ == other.lines_at_min_;
|
||||
return shifts_ == other.shifts_;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned min_resolution_ = 0;
|
||||
unsigned lines_at_min_ = 0;
|
||||
std::vector<std::size_t> shifts_;
|
||||
|
||||
template<class Stream>
|
||||
friend void serialize(Stream& str, StaggerConfig& x);
|
||||
|
@ -105,8 +105,7 @@ private:
|
|||
template<class Stream>
|
||||
void serialize(Stream& str, StaggerConfig& x)
|
||||
{
|
||||
serialize(str, x.min_resolution_);
|
||||
serialize(str, x.lines_at_min_);
|
||||
serialize(str, x.shifts_);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const StaggerConfig& config);
|
||||
|
@ -114,9 +113,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,94 +246,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_);
|
||||
}
|
||||
|
||||
|
||||
class ScanMethodFilter
|
||||
{
|
||||
public:
|
||||
struct Any {};
|
||||
static constexpr Any ANY{};
|
||||
|
||||
ScanMethodFilter() : matches_any_{false} {}
|
||||
ScanMethodFilter(Any) : matches_any_{true} {}
|
||||
ScanMethodFilter(std::initializer_list<ScanMethod> methods) :
|
||||
matches_any_{false},
|
||||
methods_{methods}
|
||||
{}
|
||||
|
||||
bool matches(ScanMethod method) const
|
||||
{
|
||||
if (matches_any_)
|
||||
return true;
|
||||
auto it = std::find(methods_.begin(), methods_.end(), method);
|
||||
return it != methods_.end();
|
||||
}
|
||||
|
||||
bool operator==(const ScanMethodFilter& other) const
|
||||
{
|
||||
return matches_any_ == other.matches_any_ && methods_ == other.methods_;
|
||||
}
|
||||
|
||||
bool matches_any() const { return matches_any_; }
|
||||
const std::vector<ScanMethod>& methods() const { return methods_; }
|
||||
|
||||
private:
|
||||
bool matches_any_ = false;
|
||||
std::vector<ScanMethod> methods_;
|
||||
|
||||
template<class Stream>
|
||||
friend void serialize(Stream& str, ResolutionFilter& x);
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const ScanMethodFilter& methods);
|
||||
|
||||
|
||||
struct Genesys_Sensor {
|
||||
|
||||
Genesys_Sensor() = default;
|
||||
|
@ -340,10 +256,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 };
|
||||
|
@ -353,27 +274,32 @@ 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 to the right from the acquired data. Calculated
|
||||
// in shading resolution.
|
||||
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;
|
||||
// TA CCD target code (reference gain)
|
||||
int fau_gain_white_ref = 0;
|
||||
// CCD target code (reference gain)
|
||||
|
@ -384,8 +310,7 @@ struct Genesys_Sensor {
|
|||
|
||||
int exposure_lperiod = -1;
|
||||
|
||||
// the number of pixels in a single segment.
|
||||
// only on gl843
|
||||
// the number of pixels in a single segment. This is counted in output resolution.
|
||||
unsigned segment_size = 0;
|
||||
|
||||
// the order of the segments, if any, for the sensor. If the sensor is not segmented or uses
|
||||
|
@ -393,32 +318,28 @@ struct Genesys_Sensor {
|
|||
// only on gl843
|
||||
std::vector<unsigned> segment_order;
|
||||
|
||||
// some CCDs use two arrays of pixels for double resolution. On such CCDs when scanning at
|
||||
// high-enough resolution, every other pixel column is shifted
|
||||
StaggerConfig stagger_config;
|
||||
// some CCDs use multiple arrays of pixels for double or quadruple resolution. This can result
|
||||
// in the following effects on the output:
|
||||
// - every n-th column may be shifted in a vertical direction.
|
||||
// - the columns themselves may be reordered in arbitrary order and may require shifting
|
||||
// in X direction.
|
||||
StaggerConfig stagger_x;
|
||||
StaggerConfig stagger_y;
|
||||
|
||||
// True if calibration should be performed on host-side
|
||||
bool use_host_side_calib = false;
|
||||
|
||||
GenesysRegisterSettingSet custom_base_regs; // gl646-specific
|
||||
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_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_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
|
||||
|
@ -444,22 +365,26 @@ 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 &&
|
||||
fau_gain_white_ref == other.fau_gain_white_ref &&
|
||||
gain_white_ref == other.gain_white_ref &&
|
||||
exposure == other.exposure &&
|
||||
exposure_lperiod == other.exposure_lperiod &&
|
||||
segment_size == other.segment_size &&
|
||||
segment_order == other.segment_order &&
|
||||
stagger_config == other.stagger_config &&
|
||||
stagger_x == other.stagger_x &&
|
||||
stagger_y == other.stagger_y &&
|
||||
use_host_side_calib == other.use_host_side_calib &&
|
||||
custom_base_regs == other.custom_base_regs &&
|
||||
custom_regs == other.custom_regs &&
|
||||
custom_fe_regs == other.custom_fe_regs &&
|
||||
gamma == other.gamma;
|
||||
|
@ -470,13 +395,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.fau_gain_white_ref);
|
||||
serialize(str, x.gain_white_ref);
|
||||
serialize_newline(str);
|
||||
|
@ -489,12 +417,12 @@ void serialize(Stream& str, Genesys_Sensor& x)
|
|||
serialize_newline(str);
|
||||
serialize(str, x.segment_order);
|
||||
serialize_newline(str);
|
||||
serialize(str, x.stagger_config);
|
||||
serialize(str, x.stagger_x);
|
||||
serialize_newline(str);
|
||||
serialize(str, x.stagger_y);
|
||||
serialize_newline(str);
|
||||
serialize(str, x.use_host_side_calib);
|
||||
serialize_newline(str);
|
||||
serialize(str, x.custom_base_regs);
|
||||
serialize_newline(str);
|
||||
serialize(str, x.custom_regs);
|
||||
serialize_newline(str);
|
||||
serialize(str, x.custom_fe_regs);
|
||||
|
|
|
@ -97,13 +97,13 @@ bool ScanSession::operator==(const ScanSession& other) const
|
|||
{
|
||||
return params == other.params &&
|
||||
computed == other.computed &&
|
||||
hwdpi_divisor == other.hwdpi_divisor &&
|
||||
ccd_size_divisor == other.ccd_size_divisor &&
|
||||
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 &&
|
||||
|
@ -117,32 +117,32 @@ bool ScanSession::operator==(const ScanSession& other) const
|
|||
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 &&
|
||||
stagger_x == other.stagger_x &&
|
||||
stagger_y == other.stagger_y &&
|
||||
segment_count == other.segment_count &&
|
||||
pixel_startx == other.pixel_startx &&
|
||||
pixel_endx == other.pixel_endx &&
|
||||
pixel_count_multiplier == other.pixel_count_multiplier &&
|
||||
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 &&
|
||||
shading_pixel_offset == other.shading_pixel_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;
|
||||
use_host_side_calib == other.use_host_side_calib;
|
||||
}
|
||||
|
||||
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'
|
||||
|
@ -153,19 +153,19 @@ std::ostream& operator<<(std::ostream& out, const ScanSession& session)
|
|||
<< " color_shift_lines_b: " << session.color_shift_lines_b << '\n'
|
||||
<< " max_color_shift_lines: " << session.max_color_shift_lines << '\n'
|
||||
<< " enable_ledadd: " << session.enable_ledadd << '\n'
|
||||
<< " stagger_x: " << session.stagger_x << '\n'
|
||||
<< " stagger_y: " << session.stagger_y << '\n'
|
||||
<< " 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'
|
||||
<< " shading_pixel_offset: " << session.shading_pixel_offset << '\n'
|
||||
<< " buffer_size_read: " << session.buffer_size_read << '\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": "")
|
||||
<< (session.pipeline_needs_shrink ? " shrink": "") << '\n'
|
||||
<< " params: " << format_indent_braced_list(4, session.params) << '\n'
|
||||
<< "}";
|
||||
return out;
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
|
||||
#include "enums.h"
|
||||
#include "serialize.h"
|
||||
#include "utilities.h"
|
||||
#include "sensor.h"
|
||||
|
||||
namespace genesys {
|
||||
|
||||
|
@ -79,15 +81,6 @@ struct Genesys_Settings
|
|||
// true if scan is true gray, false if monochrome scan
|
||||
int true_gray = 0;
|
||||
|
||||
// lineart threshold
|
||||
int threshold = 0;
|
||||
|
||||
// lineart threshold curve for dynamic rasterization
|
||||
int threshold_curve = 0;
|
||||
|
||||
// Disable interpolation for xres<yres
|
||||
int disable_interpolation = 0;
|
||||
|
||||
// value for contrast enhancement in the [-100..100] range
|
||||
int contrast = 0;
|
||||
|
||||
|
@ -120,8 +113,9 @@ struct SetupParams {
|
|||
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
|
||||
|
@ -144,7 +138,7 @@ struct SetupParams {
|
|||
|
||||
ColorFilter color_filter = static_cast<ColorFilter>(NOT_SET);
|
||||
|
||||
ScanFlag flags;
|
||||
ScanFlag flags = ScanFlag::NONE;
|
||||
|
||||
unsigned get_requested_pixels() const
|
||||
{
|
||||
|
@ -210,15 +204,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.
|
||||
|
@ -232,9 +221,11 @@ struct ScanSession {
|
|||
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;
|
||||
|
||||
|
@ -262,7 +253,7 @@ struct ScanSession {
|
|||
unsigned output_total_bytes = 0;
|
||||
|
||||
// the number of staggered lines (i.e. lines that overlap during scanning due to line being
|
||||
// thinner than the CCD element)
|
||||
// thinner than the CCD element). Computed according to stagger_y.
|
||||
unsigned num_staggered_lines = 0;
|
||||
|
||||
// the number of lines that color channels shift due to different physical positions of
|
||||
|
@ -276,6 +267,11 @@ struct ScanSession {
|
|||
// actual line shift of the blue color
|
||||
unsigned color_shift_lines_b = 0;
|
||||
|
||||
// The shifts that need to be applied to the output pixels in x direction.
|
||||
StaggerConfig stagger_x;
|
||||
// The shifts that need to be applied to the output pixels in y direction.
|
||||
StaggerConfig stagger_y;
|
||||
|
||||
// the number of scanner segments used in the current scan
|
||||
unsigned segment_count = 1;
|
||||
|
||||
|
@ -283,8 +279,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.
|
||||
|
@ -300,6 +306,10 @@ struct ScanSession {
|
|||
// Currently it's always zero.
|
||||
unsigned output_segment_start_offset = 0;
|
||||
|
||||
// How many pixels the shading data is offset to the right from the acquired data. Calculated
|
||||
// in shading resolution.
|
||||
int shading_pixel_offset = 0;
|
||||
|
||||
// the size of the read buffer.
|
||||
size_t buffer_size_read = 0;
|
||||
|
||||
|
@ -309,11 +319,6 @@ struct ScanSession {
|
|||
// 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;
|
||||
bool pipeline_needs_shrink = false;
|
||||
|
||||
void assert_computed() const
|
||||
{
|
||||
if (!computed) {
|
||||
|
@ -332,13 +337,13 @@ void serialize(Stream& str, ScanSession& x)
|
|||
serialize(str, x.params);
|
||||
serialize_newline(str);
|
||||
serialize(str, x.computed);
|
||||
serialize(str, x.hwdpi_divisor);
|
||||
serialize(str, x.ccd_size_divisor);
|
||||
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);
|
||||
|
@ -352,19 +357,19 @@ void serialize(Stream& str, ScanSession& x)
|
|||
serialize(str, x.color_shift_lines_r);
|
||||
serialize(str, x.color_shift_lines_g);
|
||||
serialize(str, x.color_shift_lines_b);
|
||||
serialize(str, x.stagger_x);
|
||||
serialize(str, x.stagger_y);
|
||||
serialize(str, x.segment_count);
|
||||
serialize(str, x.pixel_startx);
|
||||
serialize(str, x.pixel_endx);
|
||||
serialize(str, x.pixel_count_multiplier);
|
||||
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.shading_pixel_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);
|
||||
|
|
|
@ -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;
|
||||
|
@ -536,6 +583,26 @@ void genesys_init_frontend_tables()
|
|||
s_frontends->push_back(fe);
|
||||
|
||||
|
||||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::CANON_5600F;
|
||||
fe.layout = wolfson_layout;
|
||||
fe.regs = {
|
||||
{ 0x01, 0x23 },
|
||||
{ 0x02, 0x24 },
|
||||
{ 0x03, 0x2f },
|
||||
{ 0x06, 0x00 },
|
||||
{ 0x08, 0x00 },
|
||||
{ 0x09, 0x00 },
|
||||
{ 0x20, 0x60 },
|
||||
{ 0x21, 0x60 },
|
||||
{ 0x22, 0x60 },
|
||||
{ 0x28, 0x77 },
|
||||
{ 0x29, 0x77 },
|
||||
{ 0x2a, 0x77 },
|
||||
};
|
||||
s_frontends->push_back(fe);
|
||||
|
||||
|
||||
fe = Genesys_Frontend();
|
||||
fe.id = AdcId::CANON_8400F;
|
||||
fe.layout = wolfson_layout;
|
||||
|
@ -583,6 +650,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 +673,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 +700,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 = {
|
||||
|
@ -349,6 +392,22 @@ void genesys_init_gpo_tables()
|
|||
s_gpo->push_back(gpo);
|
||||
|
||||
|
||||
gpo = Genesys_Gpo();
|
||||
gpo.id = GpioId::CANON_5600F;
|
||||
gpo.regs = {
|
||||
{ 0x6b, 0x87 },
|
||||
{ 0x6c, 0xf0 },
|
||||
{ 0x6d, 0x5f },
|
||||
{ 0x6e, 0x7f },
|
||||
{ 0x6f, 0xa0 },
|
||||
{ 0xa6, 0x07 },
|
||||
{ 0xa7, 0x1c },
|
||||
{ 0xa8, 0x00 },
|
||||
{ 0xa9, 0x04 },
|
||||
};
|
||||
s_gpo->push_back(gpo);
|
||||
|
||||
|
||||
gpo = Genesys_Gpo();
|
||||
gpo.id = GpioId::CANON_8400F;
|
||||
gpo.regs = {
|
||||
|
@ -382,10 +441,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 +450,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,164 @@
|
|||
/* 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_5600F };
|
||||
ml.regs = {
|
||||
{ 0xd0, 0x0a },
|
||||
{ 0xe0, 0x01 }, { 0xe1, 0x2c }, { 0xe2, 0x06 }, { 0xe3, 0x4e },
|
||||
{ 0xe4, 0x06 }, { 0xe5, 0x4f }, { 0xe6, 0x0b }, { 0xe7, 0x71 },
|
||||
{ 0xe8, 0x0b }, { 0xe9, 0x72 }, { 0xea, 0x10 }, { 0xeb, 0x94 },
|
||||
{ 0xec, 0x10 }, { 0xed, 0x95 }, { 0xee, 0x15 }, { 0xef, 0xb7 },
|
||||
{ 0xf0, 0x15 }, { 0xf1, 0xb8 }, { 0xf2, 0x1a }, { 0xf3, 0xda },
|
||||
{ 0xf4, 0x1a }, { 0xf5, 0xdb }, { 0xf6, 0x1f }, { 0xf7, 0xfd },
|
||||
{ 0xf8, 0x05 }
|
||||
};
|
||||
s_memory_layout->push_back(ml);
|
||||
|
||||
|
||||
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();
|
||||
ml.models = { ModelId::CANON_LIDE_200 };
|
||||
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
|
|
@ -58,7 +58,7 @@
|
|||
|
||||
namespace genesys {
|
||||
|
||||
StaticInit<std::vector<Genesys_USB_Device_Entry>> s_usb_devices;
|
||||
StaticInit<std::vector<UsbDeviceEntry>> s_usb_devices;
|
||||
|
||||
void genesys_init_usb_device_tables()
|
||||
{
|
||||
|
@ -192,8 +192,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::CANON_LIDE_35;
|
||||
model.gpio_id = GpioId::CANON_LIDE_35;
|
||||
model.motor_id = MotorId::CANON_LIDE_35;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::DARK_WHITE_CALIBRATION |
|
||||
model.flags = ModelFlag::DARK_WHITE_CALIBRATION |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW |
|
||||
GENESYS_HAS_FILE_SW |
|
||||
|
@ -247,8 +246,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::KVSS080;
|
||||
model.gpio_id = GpioId::KVSS080;
|
||||
model.motor_id = MotorId::KVSS080;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.flags = ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW;
|
||||
model.search_lines = 100;
|
||||
|
||||
|
@ -298,8 +296,8 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::G4050;
|
||||
model.gpio_id = GpioId::G4050;
|
||||
model.motor_id = MotorId::G4050;
|
||||
model.flags = ModelFlag::SHADING_REPARK |
|
||||
ModelFlag::SKIP_WARMUP |
|
||||
model.flags = ModelFlag::WARMUP |
|
||||
ModelFlag::SHADING_REPARK |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_COPY_SW;
|
||||
model.search_lines = 100;
|
||||
|
@ -348,7 +346,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::G4050;
|
||||
model.gpio_id = GpioId::G4050;
|
||||
model.motor_id = MotorId::G4050;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
model.flags = ModelFlag::WARMUP |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_COPY_SW;
|
||||
|
@ -400,7 +398,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::G4050;
|
||||
model.gpio_id = GpioId::G4050;
|
||||
model.motor_id = MotorId::G4050;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
model.flags = ModelFlag::WARMUP |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_COPY_SW;
|
||||
|
@ -432,7 +430,7 @@ void genesys_init_usb_device_tables()
|
|||
model.bpp_color_values = { 8, 16 };
|
||||
|
||||
model.x_offset = 6.0;
|
||||
model.y_offset = 12.00;
|
||||
model.y_offset = 10.00;
|
||||
model.x_size = 215.9;
|
||||
model.y_size = 297.0;
|
||||
|
||||
|
@ -442,12 +440,12 @@ void genesys_init_usb_device_tables()
|
|||
model.x_size_calib_mm = 241.3;
|
||||
|
||||
model.x_offset_ta = 115.0;
|
||||
model.y_offset_ta = 60.0;
|
||||
model.y_offset_ta = 37.0;
|
||||
model.x_size_ta = 35.0;
|
||||
model.y_size_ta = 230.0;
|
||||
|
||||
model.y_offset_sensor_to_ta = 46.0;
|
||||
model.y_offset_calib_white_ta = 47.0;
|
||||
model.y_offset_sensor_to_ta = 23.0;
|
||||
model.y_offset_calib_white_ta = 24.0;
|
||||
model.y_size_calib_ta_mm = 2.0;
|
||||
|
||||
model.post_scan = 0.0;
|
||||
|
@ -465,9 +463,8 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::CANON_4400F;
|
||||
model.gpio_id = GpioId::CANON_4400F;
|
||||
model.motor_id = MotorId::CANON_4400F;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
model.flags = ModelFlag::WARMUP |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::FULL_HWDPI_MODE |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::SHADING_REPARK |
|
||||
ModelFlag::UTA_NO_SECONDARY_MOTOR;
|
||||
|
@ -538,9 +535,8 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::CANON_8400F;
|
||||
model.gpio_id = GpioId::CANON_8400F;
|
||||
model.motor_id = MotorId::CANON_8400F;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
model.flags = ModelFlag::WARMUP |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::FULL_HWDPI_MODE |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::SHADING_REPARK;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_COPY_SW;
|
||||
|
@ -581,13 +577,13 @@ void genesys_init_usb_device_tables()
|
|||
model.x_offset_calib_black = 8.0;
|
||||
model.x_size_calib_mm = 240.70734;
|
||||
|
||||
model.x_offset_ta = 94.0;
|
||||
model.y_offset_ta = 26.0;
|
||||
model.x_offset_ta = 97.0;
|
||||
model.y_offset_ta = 38.5;
|
||||
model.x_size_ta = 70.0;
|
||||
model.y_size_ta = 230.0;
|
||||
|
||||
model.y_offset_sensor_to_ta = 11.5;
|
||||
model.y_offset_calib_white_ta = 14.0;
|
||||
model.y_offset_sensor_to_ta = 23.0;
|
||||
model.y_offset_calib_white_ta = 25.5;
|
||||
model.y_size_calib_ta_mm = 3.0;
|
||||
|
||||
model.post_scan = 0.0;
|
||||
|
@ -605,9 +601,8 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::CANON_8600F;
|
||||
model.gpio_id = GpioId::CANON_8600F;
|
||||
model.motor_id = MotorId::CANON_8600F;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
model.flags = ModelFlag::WARMUP |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::FULL_HWDPI_MODE |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::SHADING_REPARK;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_COPY_SW;
|
||||
|
@ -639,7 +634,7 @@ void genesys_init_usb_device_tables()
|
|||
model.x_size = 216.07;
|
||||
model.y_size = 299.0;
|
||||
|
||||
model.y_offset_calib_white = 1.0;
|
||||
model.y_offset_calib_white = 0.4233334;
|
||||
model.y_size_calib_mm = 3.0;
|
||||
model.x_offset_calib_black = 0.0;
|
||||
model.x_size_calib_mm = 217.4241;
|
||||
|
@ -659,8 +654,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::CANON_LIDE_200;
|
||||
model.gpio_id = GpioId::CANON_LIDE_200;
|
||||
model.motor_id = MotorId::CANON_LIDE_100;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::SIS_SENSOR |
|
||||
model.flags = ModelFlag::SIS_SENSOR |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::SHADING_REPARK |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
|
@ -715,8 +709,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::CANON_LIDE_110;
|
||||
model.gpio_id = GpioId::CANON_LIDE_110;
|
||||
model.motor_id = MotorId::CANON_LIDE_110;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
model.flags = ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::SHADING_REPARK |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW |
|
||||
|
@ -769,8 +762,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::CANON_LIDE_120;
|
||||
model.gpio_id = GpioId::CANON_LIDE_120;
|
||||
model.motor_id = MotorId::CANON_LIDE_120;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
model.flags = ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::SHADING_REPARK |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW |
|
||||
|
@ -792,16 +784,15 @@ void genesys_init_usb_device_tables()
|
|||
model.resolutions = {
|
||||
{
|
||||
{ ScanMethod::FLATBED },
|
||||
// BUG: 4800 resolution crashes
|
||||
{ /*4800,*/ 2400, 1200, 600, /* 400,*/ 300, 150, 100, 75 },
|
||||
{ /*4800,*/ 2400, 1200, 600, /* 400,*/ 300, 150, 100, 75 },
|
||||
{ 4800, 2400, 1200, 600, /* 400,*/ 300, 150, 100, 75 },
|
||||
{ 4800, 2400, 1200, 600, /* 400,*/ 300, 150, 100, 75 },
|
||||
}
|
||||
};
|
||||
|
||||
model.bpp_gray_values = { 8, 16 };
|
||||
model.bpp_color_values = { 8, 16 };
|
||||
|
||||
model.x_offset = 2.2;
|
||||
model.x_offset = 2.1;
|
||||
model.y_offset = 8.7;
|
||||
model.x_size = 216.70;
|
||||
model.y_size = 297.5;
|
||||
|
@ -826,8 +817,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::CANON_LIDE_110;
|
||||
model.gpio_id = GpioId::CANON_LIDE_210;
|
||||
model.motor_id = MotorId::CANON_LIDE_210;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
model.flags = ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::SHADING_REPARK |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW |
|
||||
|
@ -850,16 +840,15 @@ void genesys_init_usb_device_tables()
|
|||
model.resolutions = {
|
||||
{
|
||||
{ ScanMethod::FLATBED },
|
||||
// BUG: 4800 resolution crashes
|
||||
{ /*4800,*/ 2400, 1200, 600, 300, 150, 100, 75 },
|
||||
{ /*4800,*/ 2400, 1200, 600, 300, 150, 100, 75 },
|
||||
{ 4800, 2400, 1200, 600, 300, 150, 100, 75 },
|
||||
{ 4800, 2400, 1200, 600, 300, 150, 100, 75 },
|
||||
}
|
||||
};
|
||||
|
||||
model.bpp_gray_values = { 8, 16 };
|
||||
model.bpp_color_values = { 8, 16 };
|
||||
|
||||
model.x_offset = 2.2;
|
||||
model.x_offset = 2.1;
|
||||
model.y_offset = 8.7;
|
||||
model.x_size = 216.70;
|
||||
model.y_size = 297.5;
|
||||
|
@ -883,8 +872,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::CANON_LIDE_110;
|
||||
model.gpio_id = GpioId::CANON_LIDE_210;
|
||||
model.motor_id = MotorId::CANON_LIDE_210;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
model.flags = ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::SHADING_REPARK |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW |
|
||||
|
@ -898,52 +886,65 @@ void genesys_init_usb_device_tables()
|
|||
|
||||
|
||||
model = Genesys_Model();
|
||||
model.name = "canon-5600f";
|
||||
model.name = "canon-canoscan-5600f";
|
||||
model.vendor = "Canon";
|
||||
model.model = "5600F";
|
||||
model.model = "CanoScan 5600F";
|
||||
model.model_id = ModelId::CANON_5600F;
|
||||
model.asic_type = AsicType::GL847;
|
||||
|
||||
model.resolutions = {
|
||||
{
|
||||
{ ScanMethod::FLATBED },
|
||||
{ 4800, 2400, 1200, 600, 400, 300, 200, 150, 100, 75 },
|
||||
{ 4800, 2400, 1200, 600, 400, 300, 200, 150, 100, 75 },
|
||||
{ ScanMethod::FLATBED, ScanMethod::TRANSPARENCY },
|
||||
{ 4800, 2400, 1200, 600, 300, /*150*/ },
|
||||
{ 4800, 2400, 1200, 600, 300, /*150*/ },
|
||||
}
|
||||
};
|
||||
|
||||
model.bpp_gray_values = { 8, 16 };
|
||||
model.bpp_color_values = { 8, 16 };
|
||||
|
||||
model.x_offset = 1.1;
|
||||
model.y_offset = 8.3;
|
||||
model.x_size = 216.07;
|
||||
model.y_size = 299.0;
|
||||
model.x_offset = 1.5;
|
||||
model.y_offset = 10.4;
|
||||
model.x_size = 219.00;
|
||||
model.y_size = 305.0;
|
||||
|
||||
model.y_offset_calib_white = 3.0;
|
||||
model.y_size_calib_mm = 3.0;
|
||||
model.y_offset_calib_white = 2.0;
|
||||
model.y_size_calib_mm = 2.0;
|
||||
model.x_offset_calib_black = 0.0;
|
||||
model.x_size_calib_mm = 217.4241;
|
||||
model.x_size_calib_mm = 220.5;
|
||||
|
||||
model.x_offset_ta = 93.0;
|
||||
model.y_offset_ta = 42.4;
|
||||
model.x_size_ta = 35.0;
|
||||
model.y_size_ta = 230.0;
|
||||
|
||||
model.y_offset_sensor_to_ta = 0;
|
||||
model.y_offset_calib_white_ta = 21.4;
|
||||
model.y_size_calib_ta_mm = 1.0;
|
||||
|
||||
model.post_scan = 0.0;
|
||||
model.eject_feed = 0.0;
|
||||
|
||||
model.ld_shift_r = 0;
|
||||
model.ld_shift_g = 0;
|
||||
model.ld_shift_b = 0;
|
||||
model.ld_shift_g = 32;
|
||||
model.ld_shift_b = 64;
|
||||
|
||||
model.line_mode_color_order = ColorOrder::RGB;
|
||||
|
||||
model.is_cis = true;
|
||||
model.is_cis = false;
|
||||
model.is_sheetfed = false;
|
||||
model.sensor_id = SensorId::CIS_CANON_LIDE_200;
|
||||
model.adc_id = AdcId::CANON_LIDE_200;
|
||||
model.gpio_id = GpioId::CANON_LIDE_200;
|
||||
model.motor_id = MotorId::CANON_LIDE_200;
|
||||
model.flags = ModelFlag::UNTESTED |
|
||||
ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::SIS_SENSOR |
|
||||
model.sensor_id = SensorId::CCD_CANON_5600F;
|
||||
model.adc_id = AdcId::CANON_5600F;
|
||||
model.gpio_id = GpioId::CANON_5600F;
|
||||
model.motor_id = MotorId::CANON_5600F;
|
||||
model.flags = ModelFlag::SIS_SENSOR |
|
||||
ModelFlag::INVERT_PIXEL_DATA |
|
||||
ModelFlag::DISABLE_ADC_CALIBRATION |
|
||||
ModelFlag::DISABLE_EXPOSURE_CALIBRATION |
|
||||
ModelFlag::HOST_SIDE_CALIBRATION_COMPLETE_SCAN |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::SHADING_REPARK |
|
||||
ModelFlag::UTA_NO_SECONDARY_MOTOR |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW |
|
||||
GENESYS_HAS_COPY_SW |
|
||||
|
@ -963,9 +964,10 @@ void genesys_init_usb_device_tables()
|
|||
|
||||
model.resolutions = {
|
||||
{
|
||||
// FIXME: support 2400 ad 4800 dpi
|
||||
{ ScanMethod::FLATBED },
|
||||
{ 4800, 2400, 1200, 600, 300, 200, 150, 100, 75 },
|
||||
{ 4800, 2400, 1200, 600, 300, 200, 150, 100, 75 },
|
||||
{ 1200, 600, 300, 200, 150, 100, 75 },
|
||||
{ 1200, 600, 300, 200, 150, 100, 75 },
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -977,7 +979,7 @@ void genesys_init_usb_device_tables()
|
|||
model.x_size = 216.07;
|
||||
model.y_size = 297.0;
|
||||
|
||||
model.y_offset_calib_white = 1.0;
|
||||
model.y_offset_calib_white = 0.4233334;
|
||||
model.y_size_calib_mm = 3.0;
|
||||
model.x_offset_calib_black = 0.0;
|
||||
model.x_size_calib_mm = 219.6254;
|
||||
|
@ -997,8 +999,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::CANON_LIDE_700F;
|
||||
model.gpio_id = GpioId::CANON_LIDE_700F;
|
||||
model.motor_id = MotorId::CANON_LIDE_700;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::SIS_SENSOR |
|
||||
model.flags = ModelFlag::SIS_SENSOR |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::SHADING_REPARK |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
|
@ -1034,7 +1035,7 @@ void genesys_init_usb_device_tables()
|
|||
model.x_size = 216.07;
|
||||
model.y_size = 299.0;
|
||||
|
||||
model.y_offset_calib_white = 0.0;
|
||||
model.y_offset_calib_white = 0.4233334;
|
||||
model.y_size_calib_mm = 3.0;
|
||||
model.x_offset_calib_black = 0.0;
|
||||
model.x_size_calib_mm = 217.4241;
|
||||
|
@ -1053,8 +1054,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::CANON_LIDE_200;
|
||||
model.gpio_id = GpioId::CANON_LIDE_200;
|
||||
model.motor_id = MotorId::CANON_LIDE_200;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::SIS_SENSOR |
|
||||
model.flags = ModelFlag::SIS_SENSOR |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::SHADING_REPARK |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
|
@ -1107,12 +1107,11 @@ void genesys_init_usb_device_tables()
|
|||
|
||||
model.is_cis = true;
|
||||
model.is_sheetfed = false;
|
||||
model.sensor_id = SensorId::CIS_CANON_LIDE_35;
|
||||
model.sensor_id = SensorId::CIS_CANON_LIDE_60;
|
||||
model.adc_id = AdcId::CANON_LIDE_35;
|
||||
model.gpio_id = GpioId::CANON_LIDE_35;
|
||||
model.motor_id = MotorId::CANON_LIDE_35;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::DARK_WHITE_CALIBRATION |
|
||||
model.motor_id = MotorId::CANON_LIDE_60;
|
||||
model.flags = ModelFlag::DARK_WHITE_CALIBRATION |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
|
||||
model.buttons = GENESYS_HAS_COPY_SW |
|
||||
|
@ -1167,8 +1166,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::CANON_LIDE_80;
|
||||
model.gpio_id = GpioId::CANON_LIDE_80;
|
||||
model.motor_id = MotorId::CANON_LIDE_80;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::DARK_WHITE_CALIBRATION |
|
||||
model.flags = ModelFlag::DARK_WHITE_CALIBRATION |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW |
|
||||
GENESYS_HAS_FILE_SW |
|
||||
|
@ -1210,8 +1208,8 @@ void genesys_init_usb_device_tables()
|
|||
model.post_scan = 0.0;
|
||||
model.eject_feed = 0.0;
|
||||
|
||||
model.ld_shift_r = 16;
|
||||
model.ld_shift_g = 8;
|
||||
model.ld_shift_r = 32;
|
||||
model.ld_shift_g = 16;
|
||||
model.ld_shift_b = 0;
|
||||
|
||||
model.line_mode_color_order = ColorOrder::RGB;
|
||||
|
@ -1222,7 +1220,6 @@ void genesys_init_usb_device_tables()
|
|||
model.gpio_id = GpioId::HP2300;
|
||||
model.motor_id = MotorId::HP2300;
|
||||
model.flags = ModelFlag::GAMMA_14BIT |
|
||||
ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW;
|
||||
|
@ -1276,7 +1273,6 @@ void genesys_init_usb_device_tables()
|
|||
model.motor_id = MotorId::HP2400;
|
||||
model.flags = ModelFlag::GAMMA_14BIT |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_SCAN_SW;
|
||||
model.search_lines = 132;
|
||||
|
@ -1329,7 +1325,6 @@ void genesys_init_usb_device_tables()
|
|||
model.motor_id = MotorId::XP200;
|
||||
model.flags = ModelFlag::GAMMA_14BIT |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::DARK_CALIBRATION;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
|
||||
model.search_lines = 132;
|
||||
|
@ -1380,7 +1375,8 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::WOLFSON_HP3670;
|
||||
model.gpio_id = GpioId::HP3670;
|
||||
model.motor_id = MotorId::HP3670;
|
||||
model.flags = ModelFlag::GAMMA_14BIT |
|
||||
model.flags = ModelFlag::WARMUP |
|
||||
ModelFlag::GAMMA_14BIT |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_SCAN_SW;
|
||||
|
@ -1520,8 +1516,8 @@ void genesys_init_usb_device_tables()
|
|||
model.post_scan = 0.0;
|
||||
model.eject_feed = 0.0;
|
||||
|
||||
model.ld_shift_r = 48;
|
||||
model.ld_shift_g = 24;
|
||||
model.ld_shift_r = 96;
|
||||
model.ld_shift_g = 48;
|
||||
model.ld_shift_b = 0;
|
||||
model.line_mode_color_order = ColorOrder::RGB;
|
||||
|
||||
|
@ -1531,7 +1527,8 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::WOLFSON_5345;
|
||||
model.gpio_id = GpioId::MD_5345;
|
||||
model.motor_id = MotorId::MD_5345;
|
||||
model.flags = ModelFlag::GAMMA_14BIT |
|
||||
model.flags = ModelFlag::WARMUP |
|
||||
ModelFlag::GAMMA_14BIT |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_COPY_SW |
|
||||
|
@ -1586,8 +1583,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::WOLFSON_XP300;
|
||||
model.gpio_id = GpioId::XP300;
|
||||
model.motor_id = MotorId::XP300;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
model.flags = ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
|
||||
model.search_lines = 400;
|
||||
|
@ -1637,8 +1633,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::WOLFSON_XP300;
|
||||
model.gpio_id = GpioId::DP665;
|
||||
model.motor_id = MotorId::DP665;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
model.flags = ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
|
||||
model.search_lines = 400;
|
||||
|
@ -1688,8 +1683,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::WOLFSON_XP300;
|
||||
model.gpio_id = GpioId::DP665;
|
||||
model.motor_id = MotorId::ROADWARRIOR;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
model.flags = ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::DARK_CALIBRATION;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
|
||||
model.search_lines = 400;
|
||||
|
@ -1739,8 +1733,9 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::WOLFSON_XP300;
|
||||
model.gpio_id = GpioId::DP665;
|
||||
model.motor_id = MotorId::ROADWARRIOR;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::NO_CALIBRATION |
|
||||
model.flags = ModelFlag::DISABLE_ADC_CALIBRATION |
|
||||
ModelFlag::DISABLE_EXPOSURE_CALIBRATION |
|
||||
ModelFlag::DISABLE_SHADING_CALIBRATION |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::UNTESTED;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW;
|
||||
|
@ -1792,8 +1787,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::WOLFSON_XP300;
|
||||
model.gpio_id = GpioId::DP665;
|
||||
model.motor_id = MotorId::ROADWARRIOR;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
model.flags = ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::DARK_CALIBRATION;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
|
||||
model.search_lines = 400;
|
||||
|
@ -1843,8 +1837,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::WOLFSON_DSM600;
|
||||
model.gpio_id = GpioId::DP665;
|
||||
model.motor_id = MotorId::DSMOBILE_600;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
model.flags = ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::DARK_CALIBRATION;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
|
||||
model.search_lines = 400;
|
||||
|
@ -1895,8 +1888,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::WOLFSON_DSM600;
|
||||
model.gpio_id = GpioId::DP665;
|
||||
model.motor_id = MotorId::DSMOBILE_600;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
model.flags = ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::DARK_CALIBRATION;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
|
||||
model.search_lines = 400;
|
||||
|
@ -1946,8 +1938,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::WOLFSON_DSM600;
|
||||
model.gpio_id = GpioId::DP685;
|
||||
model.motor_id = MotorId::XP300;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
model.flags = ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::DARK_CALIBRATION;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
|
||||
model.search_lines = 400;
|
||||
|
@ -1999,8 +1990,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::WOLFSON_XP300;
|
||||
model.gpio_id = GpioId::XP300;
|
||||
model.motor_id = MotorId::XP300;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
model.flags = ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::DARK_CALIBRATION;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
|
||||
model.search_lines = 400;
|
||||
|
@ -2048,12 +2038,11 @@ void genesys_init_usb_device_tables()
|
|||
|
||||
model.is_cis = true;
|
||||
model.is_sheetfed = true;
|
||||
model.sensor_id = SensorId::CCD_XP300;
|
||||
model.sensor_id = SensorId::CCD_DOCKETPORT_487;
|
||||
model.adc_id = AdcId::WOLFSON_XP300;
|
||||
model.gpio_id = GpioId::XP300;
|
||||
model.motor_id = MotorId::XP300;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
model.flags = ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::UNTESTED;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
|
||||
|
@ -2093,8 +2082,8 @@ void genesys_init_usb_device_tables()
|
|||
model.post_scan = 0.0;
|
||||
model.eject_feed = 0.0;
|
||||
|
||||
model.ld_shift_r = 48;
|
||||
model.ld_shift_g = 24;
|
||||
model.ld_shift_r = 96;
|
||||
model.ld_shift_g = 48;
|
||||
model.ld_shift_b = 0;
|
||||
model.line_mode_color_order = ColorOrder::RGB;
|
||||
|
||||
|
@ -2104,7 +2093,8 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::WOLFSON_5345;
|
||||
model.gpio_id = GpioId::MD_5345;
|
||||
model.motor_id = MotorId::MD_5345;
|
||||
model.flags = ModelFlag::GAMMA_14BIT |
|
||||
model.flags = ModelFlag::WARMUP |
|
||||
ModelFlag::GAMMA_14BIT |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_COPY_SW |
|
||||
|
@ -2148,8 +2138,8 @@ void genesys_init_usb_device_tables()
|
|||
model.post_scan = 0.0;
|
||||
model.eject_feed = 0.0;
|
||||
|
||||
model.ld_shift_r = 48;
|
||||
model.ld_shift_g = 24;
|
||||
model.ld_shift_r = 96;
|
||||
model.ld_shift_g = 48;
|
||||
model.ld_shift_b = 0;
|
||||
model.line_mode_color_order = ColorOrder::RGB;
|
||||
|
||||
|
@ -2159,7 +2149,8 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::WOLFSON_5345;
|
||||
model.gpio_id = GpioId::MD_5345;
|
||||
model.motor_id = MotorId::MD_5345;
|
||||
model.flags = ModelFlag::GAMMA_14BIT |
|
||||
model.flags = ModelFlag::WARMUP |
|
||||
ModelFlag::GAMMA_14BIT |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_COPY_SW |
|
||||
|
@ -2215,8 +2206,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::WOLFSON_XP300;
|
||||
model.gpio_id = GpioId::DP665;
|
||||
model.motor_id = MotorId::ROADWARRIOR;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
model.flags = ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::DARK_CALIBRATION;
|
||||
model.buttons = GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE;
|
||||
model.search_lines = 400;
|
||||
|
@ -2269,7 +2259,6 @@ void genesys_init_usb_device_tables()
|
|||
model.motor_id = MotorId::PLUSTEK_OPTICPRO_3600;
|
||||
model.flags = ModelFlag::UNTESTED | // not fully working yet
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::DARK_CALIBRATION;
|
||||
model.buttons = GENESYS_HAS_NO_BUTTONS;
|
||||
model.search_lines = 200;
|
||||
|
@ -2277,6 +2266,72 @@ void genesys_init_usb_device_tables()
|
|||
s_usb_devices->emplace_back(0x07b3, 0x0900, model);
|
||||
|
||||
|
||||
|
||||
model = Genesys_Model();
|
||||
model.name = "plustek-opticfilm-7200";
|
||||
model.vendor = "PLUSTEK";
|
||||
model.model = "OpticFilm 7200";
|
||||
model.model_id = ModelId::PLUSTEK_OPTICFILM_7200;
|
||||
model.asic_type = AsicType::GL842;
|
||||
|
||||
model.resolutions = {
|
||||
{
|
||||
{ ScanMethod::TRANSPARENCY },
|
||||
{ 7200, 3600, 1800, 900 },
|
||||
{ 7200, 3600, 1800, 900 },
|
||||
}
|
||||
};
|
||||
|
||||
model.bpp_gray_values = { 16 };
|
||||
model.bpp_color_values = { 16 };
|
||||
model.default_method = ScanMethod::TRANSPARENCY;
|
||||
|
||||
model.x_offset = 0.0;
|
||||
model.y_offset = 0.0;
|
||||
model.x_size = 36.0;
|
||||
model.y_size = 44.0;
|
||||
|
||||
model.y_offset_calib_white = 0.0;
|
||||
model.y_size_calib_mm = 0.0;
|
||||
model.x_offset_calib_black = 6.5;
|
||||
model.x_size_calib_mm = 35.9834;
|
||||
|
||||
model.x_offset_ta = 0.7f;
|
||||
model.y_offset_ta = 28.0;
|
||||
model.x_size_ta = 36.0;
|
||||
model.y_size_ta = 25.0;
|
||||
|
||||
model.y_offset_sensor_to_ta = 0.0;
|
||||
model.y_offset_calib_black_ta = 6.5;
|
||||
model.y_offset_calib_white_ta = 0.0;
|
||||
model.y_size_calib_ta_mm = 2.0;
|
||||
|
||||
model.post_scan = 0.0;
|
||||
model.eject_feed = 0.0;
|
||||
|
||||
model.ld_shift_r = 0;
|
||||
model.ld_shift_g = 12;
|
||||
model.ld_shift_b = 24;
|
||||
|
||||
model.line_mode_color_order = ColorOrder::RGB;
|
||||
|
||||
model.is_cis = false;
|
||||
model.is_sheetfed = false;
|
||||
|
||||
model.sensor_id = SensorId::CCD_PLUSTEK_OPTICFILM_7200;
|
||||
model.adc_id = AdcId::PLUSTEK_OPTICFILM_7200;
|
||||
model.gpio_id = GpioId::PLUSTEK_OPTICFILM_7200;
|
||||
model.motor_id = MotorId::PLUSTEK_OPTICFILM_7200;
|
||||
|
||||
model.flags = ModelFlag::WARMUP |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::SHADING_REPARK;
|
||||
|
||||
model.search_lines = 200;
|
||||
s_usb_devices->emplace_back(0x07b3, 0x0807, model);
|
||||
|
||||
|
||||
model = Genesys_Model();
|
||||
model.name = "plustek-opticfilm-7200i";
|
||||
model.vendor = "PLUSTEK";
|
||||
|
@ -2333,16 +2388,29 @@ void genesys_init_usb_device_tables()
|
|||
model.gpio_id = GpioId::PLUSTEK_OPTICFILM_7200I;
|
||||
model.motor_id = MotorId::PLUSTEK_OPTICFILM_7200I;
|
||||
|
||||
model.flags = ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::SKIP_WARMUP |
|
||||
model.flags = ModelFlag::WARMUP |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::SHADING_REPARK |
|
||||
ModelFlag::INVERTED_16BIT_DATA;
|
||||
ModelFlag::SWAP_16BIT_DATA;
|
||||
|
||||
model.search_lines = 200;
|
||||
s_usb_devices->emplace_back(0x07b3, 0x0c04, model);
|
||||
|
||||
|
||||
// same as 7200i, just without the infrared channel
|
||||
model.name = "plustek-opticfilm-7200-v2";
|
||||
model.model = "OpticFilm 7200 v2";
|
||||
model.resolutions = {
|
||||
{
|
||||
{ ScanMethod::TRANSPARENCY },
|
||||
{ 7200, 3600, 1800, 900 },
|
||||
{ 7200, 3600, 1800, 900 },
|
||||
}
|
||||
};
|
||||
s_usb_devices->emplace_back(0x07b3, 0x0c07, model);
|
||||
|
||||
|
||||
model = Genesys_Model();
|
||||
model.name = "plustek-opticfilm-7300";
|
||||
model.vendor = "PLUSTEK";
|
||||
|
@ -2399,8 +2467,8 @@ void genesys_init_usb_device_tables()
|
|||
model.gpio_id = GpioId::PLUSTEK_OPTICFILM_7300;
|
||||
model.motor_id = MotorId::PLUSTEK_OPTICFILM_7300;
|
||||
|
||||
model.flags = ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::SKIP_WARMUP |
|
||||
model.flags = ModelFlag::WARMUP |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::SHADING_REPARK;
|
||||
|
||||
|
@ -2408,6 +2476,82 @@ void genesys_init_usb_device_tables()
|
|||
s_usb_devices->emplace_back(0x07b3, 0x0c12, model);
|
||||
|
||||
|
||||
// same as 7300, same USB ID as 7400-v2
|
||||
model.name = "plustek-opticfilm-7400-v1";
|
||||
model.model = "OpticFilm 7400 (v1)";
|
||||
s_usb_devices->emplace_back(0x07b3, 0x0c3a, 0x0400, model);
|
||||
|
||||
|
||||
model = Genesys_Model();
|
||||
model.name = "plustek-opticfilm-7400-v2";
|
||||
model.vendor = "PLUSTEK";
|
||||
model.model = "OpticFilm 7400 (v2)";
|
||||
model.model_id = ModelId::PLUSTEK_OPTICFILM_7400;
|
||||
model.asic_type = AsicType::GL845;
|
||||
|
||||
model.resolutions = {
|
||||
{
|
||||
{ ScanMethod::TRANSPARENCY },
|
||||
{ 7200, 3600, 2400, 1200, 600 },
|
||||
{ 7200, 3600, 2400, 1200, 600 },
|
||||
}
|
||||
};
|
||||
|
||||
model.bpp_gray_values = { 16 };
|
||||
model.bpp_color_values = { 16 };
|
||||
model.default_method = ScanMethod::TRANSPARENCY;
|
||||
|
||||
model.x_offset = 0.0;
|
||||
model.y_offset = 0.0;
|
||||
model.x_size = 36.0;
|
||||
model.y_size = 44.0;
|
||||
|
||||
model.y_offset_calib_white = 0.0;
|
||||
model.y_size_calib_mm = 0.0;
|
||||
model.x_offset_calib_black = 6.5;
|
||||
model.x_size_calib_mm = 36.83;
|
||||
|
||||
model.x_offset_ta = 0.5;
|
||||
model.y_offset_ta = 29.0;
|
||||
model.x_size_ta = 36.33;
|
||||
model.y_size_ta = 25.0;
|
||||
|
||||
model.y_offset_sensor_to_ta = 0.0;
|
||||
model.y_offset_calib_black_ta = 6.5;
|
||||
model.y_offset_calib_white_ta = 0.0;
|
||||
model.y_size_calib_ta_mm = 2.0;
|
||||
|
||||
model.post_scan = 0.0;
|
||||
model.eject_feed = 0.0;
|
||||
|
||||
model.ld_shift_r = 0;
|
||||
model.ld_shift_g = 12;
|
||||
model.ld_shift_b = 24;
|
||||
|
||||
model.line_mode_color_order = ColorOrder::RGB;
|
||||
|
||||
model.is_cis = false;
|
||||
model.is_sheetfed = false;
|
||||
|
||||
model.sensor_id = SensorId::CCD_PLUSTEK_OPTICFILM_7400;
|
||||
model.adc_id = AdcId::PLUSTEK_OPTICFILM_7400;
|
||||
model.gpio_id = GpioId::PLUSTEK_OPTICFILM_7400;
|
||||
model.motor_id = MotorId::PLUSTEK_OPTICFILM_7400;
|
||||
|
||||
model.flags = ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::SHADING_REPARK;
|
||||
|
||||
model.search_lines = 200;
|
||||
s_usb_devices->emplace_back(0x07b3, 0x0c3a, 0x0605, model);
|
||||
|
||||
|
||||
// same as 7400-v2
|
||||
model.name = "plustek-opticfilm-8100";
|
||||
model.model = "OpticFilm 8100";
|
||||
s_usb_devices->emplace_back(0x07b3, 0x130c, model);
|
||||
|
||||
|
||||
model = Genesys_Model();
|
||||
model.name = "plustek-opticfilm-7500i";
|
||||
model.vendor = "PLUSTEK";
|
||||
|
@ -2464,8 +2608,8 @@ void genesys_init_usb_device_tables()
|
|||
model.gpio_id = GpioId::PLUSTEK_OPTICFILM_7500I;
|
||||
model.motor_id = MotorId::PLUSTEK_OPTICFILM_7500I;
|
||||
|
||||
model.flags = ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::SKIP_WARMUP |
|
||||
model.flags = ModelFlag::WARMUP |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::SHADING_REPARK;
|
||||
|
||||
|
@ -2473,6 +2617,82 @@ void genesys_init_usb_device_tables()
|
|||
s_usb_devices->emplace_back(0x07b3, 0x0c13, model);
|
||||
|
||||
|
||||
// same as 7500i
|
||||
model.name = "plustek-opticfilm-7600i-v1";
|
||||
model.model = "OpticFilm 7600i (v1)";
|
||||
s_usb_devices->emplace_back(0x07b3, 0x0c3b, 0x0400, model);
|
||||
|
||||
|
||||
model = Genesys_Model();
|
||||
model.name = "plustek-opticfilm-8200i";
|
||||
model.vendor = "PLUSTEK";
|
||||
model.model = "OpticFilm 8200i";
|
||||
model.model_id = ModelId::PLUSTEK_OPTICFILM_8200I;
|
||||
model.asic_type = AsicType::GL845;
|
||||
|
||||
model.resolutions = {
|
||||
{
|
||||
{ ScanMethod::TRANSPARENCY, ScanMethod::TRANSPARENCY_INFRARED },
|
||||
{ 7200, 3600, 1800, 900 },
|
||||
{ 7200, 3600, 1800, 900 },
|
||||
}
|
||||
};
|
||||
|
||||
model.bpp_gray_values = { 16 };
|
||||
model.bpp_color_values = { 16 };
|
||||
model.default_method = ScanMethod::TRANSPARENCY;
|
||||
|
||||
model.x_offset = 0.0;
|
||||
model.y_offset = 0.0;
|
||||
model.x_size = 36.0;
|
||||
model.y_size = 44.0;
|
||||
|
||||
model.y_offset_calib_white = 0.0;
|
||||
model.y_size_calib_mm = 0.0;
|
||||
model.x_offset_calib_black = 6.5;
|
||||
model.x_size_calib_mm = 36.83;
|
||||
|
||||
model.x_offset_ta = 0.5;
|
||||
model.y_offset_ta = 28.5;
|
||||
model.x_size_ta = 36.33;
|
||||
model.y_size_ta = 25.0;
|
||||
|
||||
model.y_offset_sensor_to_ta = 0.0;
|
||||
model.y_offset_calib_black_ta = 6.5;
|
||||
model.y_offset_calib_white_ta = 0.0;
|
||||
model.y_size_calib_ta_mm = 2.0;
|
||||
|
||||
model.post_scan = 0.0;
|
||||
model.eject_feed = 0.0;
|
||||
|
||||
model.ld_shift_r = 0;
|
||||
model.ld_shift_g = 12;
|
||||
model.ld_shift_b = 24;
|
||||
|
||||
model.line_mode_color_order = ColorOrder::RGB;
|
||||
|
||||
model.is_cis = false;
|
||||
model.is_sheetfed = false;
|
||||
|
||||
model.sensor_id = SensorId::CCD_PLUSTEK_OPTICFILM_8200I;
|
||||
model.adc_id = AdcId::PLUSTEK_OPTICFILM_8200I;
|
||||
model.gpio_id = GpioId::PLUSTEK_OPTICFILM_8200I;
|
||||
model.motor_id = MotorId::PLUSTEK_OPTICFILM_8200I;
|
||||
|
||||
model.flags = ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::SHADING_REPARK;
|
||||
|
||||
model.search_lines = 200;
|
||||
s_usb_devices->emplace_back(0x07b3, 0x130d, model);
|
||||
|
||||
|
||||
// same as 8200i
|
||||
model.name = "plustek-opticfilm-7600i-v2";
|
||||
model.model = "OpticFilm 7600i (v2)";
|
||||
s_usb_devices->emplace_back(0x07b3, 0x0c3b, 0x0605, model);
|
||||
|
||||
|
||||
model = Genesys_Model();
|
||||
model.name = "hewlett-packard-scanjet-N6310";
|
||||
model.vendor = "Hewlett Packard";
|
||||
|
@ -2520,8 +2740,9 @@ void genesys_init_usb_device_tables()
|
|||
ModelFlag::GAMMA_14BIT |
|
||||
ModelFlag::DARK_CALIBRATION |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::NO_CALIBRATION;
|
||||
ModelFlag::DISABLE_ADC_CALIBRATION |
|
||||
ModelFlag::DISABLE_EXPOSURE_CALIBRATION |
|
||||
ModelFlag::DISABLE_SHADING_CALIBRATION;
|
||||
|
||||
model.buttons = GENESYS_HAS_NO_BUTTONS;
|
||||
model.search_lines = 100;
|
||||
|
@ -2572,8 +2793,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::PLUSTEK_OPTICBOOK_3800;
|
||||
model.gpio_id = GpioId::PLUSTEK_OPTICBOOK_3800;
|
||||
model.motor_id = MotorId::PLUSTEK_OPTICBOOK_3800;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::CUSTOM_GAMMA;
|
||||
model.flags = ModelFlag::CUSTOM_GAMMA;
|
||||
model.buttons = GENESYS_HAS_NO_BUTTONS; // TODO there are 4 buttons to support
|
||||
model.search_lines = 100;
|
||||
|
||||
|
@ -2623,8 +2843,7 @@ void genesys_init_usb_device_tables()
|
|||
model.adc_id = AdcId::IMG101;
|
||||
model.gpio_id = GpioId::IMG101;
|
||||
model.motor_id = MotorId::IMG101;
|
||||
model.flags = ModelFlag::SKIP_WARMUP |
|
||||
ModelFlag::CUSTOM_GAMMA |
|
||||
model.flags = ModelFlag::CUSTOM_GAMMA |
|
||||
ModelFlag::UNTESTED;
|
||||
model.buttons = GENESYS_HAS_NO_BUTTONS ;
|
||||
model.search_lines = 100;
|
||||
|
@ -2635,7 +2854,7 @@ void genesys_init_usb_device_tables()
|
|||
void verify_usb_device_tables()
|
||||
{
|
||||
for (const auto& device : *s_usb_devices) {
|
||||
const auto& model = device.model;
|
||||
const auto& model = device.model();
|
||||
|
||||
if (model.x_size_calib_mm == 0.0f) {
|
||||
throw SaneException("Calibration width can't be zero");
|
||||
|
|
|
@ -57,8 +57,7 @@ void genesys_init_motor_tables()
|
|||
|
||||
Genesys_Motor motor;
|
||||
motor.id = MotorId::UMAX;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 2400;
|
||||
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));
|
||||
|
@ -66,8 +65,7 @@ void genesys_init_motor_tables()
|
|||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::MD_5345; // MD5345/6228/6471
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 2400;
|
||||
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));
|
||||
|
@ -76,7 +74,6 @@ void genesys_init_motor_tables()
|
|||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::ST24;
|
||||
motor.base_ydpi = 2400;
|
||||
motor.optical_ydpi = 2400;
|
||||
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));
|
||||
|
@ -85,7 +82,6 @@ void genesys_init_motor_tables()
|
|||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::HP3670;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 1200;
|
||||
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));
|
||||
|
@ -94,7 +90,6 @@ void genesys_init_motor_tables()
|
|||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::HP2400;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 1200;
|
||||
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));
|
||||
|
@ -102,8 +97,7 @@ void genesys_init_motor_tables()
|
|||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::HP2300;
|
||||
motor.base_ydpi = 600;
|
||||
motor.optical_ydpi = 1200;
|
||||
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));
|
||||
|
@ -112,62 +106,127 @@ void genesys_init_motor_tables()
|
|||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_LIDE_35;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 2400;
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(3500, 1300, 60), StepType::FULL, 0});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(3500, 1400, 60), StepType::HALF, 0});
|
||||
|
||||
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.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.profiles.push_back({MotorSlope::create_from_steps(3700, 3700, 2), StepType::FULL, 0});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(11000, 11000, 2), StepType::HALF, 0});
|
||||
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.profiles.push_back({MotorSlope::create_from_steps(3000, 2500, 10), StepType::FULL, 0});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(11000, 11000, 2), StepType::HALF, 0});
|
||||
|
||||
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.profiles.push_back({MotorSlope::create_from_steps(3000, 2600, 10), StepType::FULL, 0});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(11000, 11000, 2), StepType::HALF, 0});
|
||||
|
||||
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.profiles.push_back({MotorSlope::create_from_steps(6666, 3700, 8), StepType::FULL, 0});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(6666, 3700, 8), StepType::HALF, 0});
|
||||
|
||||
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.profiles.push_back({MotorSlope::create_from_steps(46876, 864, 255),
|
||||
StepType::HALF, 1432});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 864, 279),
|
||||
|
@ -180,7 +239,6 @@ void genesys_init_motor_tables()
|
|||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_LIDE_200;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 6400;
|
||||
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),
|
||||
|
@ -195,7 +253,6 @@ void genesys_init_motor_tables()
|
|||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_LIDE_700;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 6400;
|
||||
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),
|
||||
|
@ -212,7 +269,6 @@ void genesys_init_motor_tables()
|
|||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::KVSS080;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 1200;
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(44444, 500, 489),
|
||||
StepType::HALF, 8000});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
@ -221,7 +277,6 @@ void genesys_init_motor_tables()
|
|||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::G4050;
|
||||
motor.base_ydpi = 2400;
|
||||
motor.optical_ydpi = 9600;
|
||||
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),
|
||||
|
@ -236,7 +291,6 @@ void genesys_init_motor_tables()
|
|||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_4400F;
|
||||
motor.base_ydpi = 2400;
|
||||
motor.optical_ydpi = 9600;
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(28597 * 2, 727 * 2, 200);
|
||||
|
@ -261,16 +315,43 @@ void genesys_init_motor_tables()
|
|||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_5600F;
|
||||
motor.base_ydpi = 2400;
|
||||
|
||||
// FIXME: real limit is 134, but for some reason the motor can't acquire that speed.
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(2500 * 2, 134 * 2, 1000);
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.motor_vref = 0;
|
||||
profile.resolutions = { 75, 150 };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(2500 * 2, 200 * 2, 1000);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 0;
|
||||
profile.resolutions = { 300, 600, 1200, 2400, 4800 };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(2500 * 2, 200 * 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;
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(20202 * 4, 333 * 4, 100);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 0;
|
||||
profile.resolutions = ResolutionFilter::ANY;
|
||||
profile.resolutions = VALUE_FILTER_ANY;
|
||||
profile.scan_methods = { ScanMethod::FLATBED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
|
@ -278,7 +359,7 @@ void genesys_init_motor_tables()
|
|||
profile.slope = MotorSlope::create_from_steps(65535 * 4, 333 * 4, 100);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 2;
|
||||
profile.resolutions = ResolutionFilter::ANY;
|
||||
profile.resolutions = VALUE_FILTER_ANY;
|
||||
profile.scan_methods = { ScanMethod::TRANSPARENCY, ScanMethod::TRANSPARENCY_INFRARED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
|
@ -286,8 +367,8 @@ void genesys_init_motor_tables()
|
|||
profile.slope = MotorSlope::create_from_steps(65535 * 4, 333 * 4, 200);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 2;
|
||||
profile.resolutions = ResolutionFilter::ANY;
|
||||
profile.scan_methods = ScanMethodFilter::ANY;
|
||||
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));
|
||||
|
@ -296,7 +377,6 @@ void genesys_init_motor_tables()
|
|||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_8600F;
|
||||
motor.base_ydpi = 2400;
|
||||
motor.optical_ydpi = 9600;
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
|
||||
|
@ -361,7 +441,6 @@ void genesys_init_motor_tables()
|
|||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_LIDE_110;
|
||||
motor.base_ydpi = 4800;
|
||||
motor.optical_ydpi = 9600;
|
||||
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),
|
||||
|
@ -376,7 +455,6 @@ void genesys_init_motor_tables()
|
|||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_LIDE_120;
|
||||
motor.base_ydpi = 4800;
|
||||
motor.optical_ydpi = 9600;
|
||||
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),
|
||||
|
@ -391,7 +469,6 @@ void genesys_init_motor_tables()
|
|||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_LIDE_210;
|
||||
motor.base_ydpi = 4800;
|
||||
motor.optical_ydpi = 9600;
|
||||
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),
|
||||
|
@ -400,22 +477,45 @@ void genesys_init_motor_tables()
|
|||
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.profiles.push_back({MotorSlope::create_from_steps(3500, 1300, 60), StepType::FULL, 0});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(3500, 3250, 60), StepType::HALF, 0});
|
||||
|
||||
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);
|
||||
|
@ -435,7 +535,6 @@ void genesys_init_motor_tables()
|
|||
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);
|
||||
|
@ -452,10 +551,22 @@ void genesys_init_motor_tables()
|
|||
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);
|
||||
|
@ -472,10 +583,22 @@ void genesys_init_motor_tables()
|
|||
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.profiles.push_back({MotorSlope::create_from_steps(22000, 1000, 1017),
|
||||
StepType::HALF, 11000});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
@ -484,7 +607,6 @@ void genesys_init_motor_tables()
|
|||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::PLUSTEK_OPTICBOOK_3800;
|
||||
motor.base_ydpi = 600;
|
||||
motor.optical_ydpi = 1200;
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(22000, 1000, 1017),
|
||||
StepType::HALF, 11000});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
@ -493,7 +615,6 @@ void genesys_init_motor_tables()
|
|||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::CANON_LIDE_80;
|
||||
motor.base_ydpi = 2400;
|
||||
motor.optical_ydpi = 4800; // 9600
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(9560, 1912, 31), StepType::FULL, 0});
|
||||
s_motors->push_back(std::move(motor));
|
||||
}
|
||||
|
|
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 ||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,6 +46,7 @@
|
|||
|
||||
#include "error.h"
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
@ -75,6 +76,51 @@ inline double fixed_to_double(SANE_Word v)
|
|||
return static_cast<double>(v) / (1 << SANE_FIXED_SCALE_SHIFT);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T abs_diff(T a, T b)
|
||||
{
|
||||
if (a < b) {
|
||||
return b - a;
|
||||
} else {
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
|
||||
inline std::uint64_t align_multiple_floor(std::uint64_t x, std::uint64_t multiple)
|
||||
{
|
||||
if (multiple == 0) {
|
||||
return x;
|
||||
}
|
||||
return (x / multiple) * multiple;
|
||||
}
|
||||
|
||||
inline std::uint64_t align_multiple_ceil(std::uint64_t x, std::uint64_t multiple)
|
||||
{
|
||||
if (multiple == 0) {
|
||||
return x;
|
||||
}
|
||||
return ((x + multiple - 1) / multiple) * multiple;
|
||||
}
|
||||
|
||||
inline std::uint64_t multiply_by_depth_ceil(std::uint64_t pixels, std::uint64_t depth)
|
||||
{
|
||||
if (depth == 1) {
|
||||
return (pixels / 8) + ((pixels % 8) ? 1 : 0);
|
||||
} else {
|
||||
return pixels * (depth / 8);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T clamp(const T& value, const T& lo, const T& hi)
|
||||
{
|
||||
if (value < lo)
|
||||
return lo;
|
||||
if (value > hi)
|
||||
return hi;
|
||||
return value;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void compute_array_percentile_approx(T* result, const T* data,
|
||||
std::size_t line_count, std::size_t elements_per_line,
|
||||
|
@ -108,6 +154,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
|
||||
{
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef BACKEND_GENESYS_VALUE_FILTER_H
|
||||
#define BACKEND_GENESYS_VALUE_FILTER_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
namespace genesys {
|
||||
|
||||
struct AnyTag {};
|
||||
constexpr AnyTag VALUE_FILTER_ANY{};
|
||||
|
||||
template<class T>
|
||||
class ValueFilterAny
|
||||
{
|
||||
public:
|
||||
ValueFilterAny() : matches_any_{false} {}
|
||||
ValueFilterAny(AnyTag) : matches_any_{true} {}
|
||||
ValueFilterAny(std::initializer_list<T> values) :
|
||||
matches_any_{false},
|
||||
values_{values}
|
||||
{}
|
||||
|
||||
bool matches(T value) const
|
||||
{
|
||||
if (matches_any_)
|
||||
return true;
|
||||
auto it = std::find(values_.begin(), values_.end(), value);
|
||||
return it != values_.end();
|
||||
}
|
||||
|
||||
bool operator==(const ValueFilterAny& other) const
|
||||
{
|
||||
return matches_any_ == other.matches_any_ && values_ == other.values_;
|
||||
}
|
||||
|
||||
bool matches_any() const { return matches_any_; }
|
||||
const std::vector<T>& values() const { return values_; }
|
||||
|
||||
private:
|
||||
bool matches_any_ = false;
|
||||
std::vector<T> values_;
|
||||
|
||||
template<class Stream, class U>
|
||||
friend void serialize(Stream& str, ValueFilterAny<U>& x);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
std::ostream& operator<<(std::ostream& out, const ValueFilterAny<T>& values)
|
||||
{
|
||||
if (values.matches_any()) {
|
||||
out << "ANY";
|
||||
return out;
|
||||
}
|
||||
out << format_vector_indent_braced(4, "", values.values());
|
||||
return out;
|
||||
}
|
||||
|
||||
template<class Stream, class T>
|
||||
void serialize(Stream& str, ValueFilterAny<T>& x)
|
||||
{
|
||||
serialize(str, x.matches_any_);
|
||||
serialize_newline(str);
|
||||
serialize(str, x.values_);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
class ValueFilter
|
||||
{
|
||||
public:
|
||||
ValueFilter() = default;
|
||||
ValueFilter(std::initializer_list<T> values) :
|
||||
values_{values}
|
||||
{}
|
||||
|
||||
bool matches(T value) const
|
||||
{
|
||||
auto it = std::find(values_.begin(), values_.end(), value);
|
||||
return it != values_.end();
|
||||
}
|
||||
|
||||
bool operator==(const ValueFilter& other) const
|
||||
{
|
||||
return values_ == other.values_;
|
||||
}
|
||||
|
||||
const std::vector<T>& values() const { return values_; }
|
||||
|
||||
private:
|
||||
std::vector<T> values_;
|
||||
|
||||
template<class Stream, class U>
|
||||
friend void serialize(Stream& str, ValueFilter<U>& x);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
std::ostream& operator<<(std::ostream& out, const ValueFilter<T>& values)
|
||||
{
|
||||
if (values.values().empty()) {
|
||||
out << "(none)";
|
||||
return out;
|
||||
}
|
||||
out << format_vector_indent_braced(4, "", values.values());
|
||||
return out;
|
||||
}
|
||||
|
||||
template<class Stream, class T>
|
||||
void serialize(Stream& str, ValueFilter<T>& x)
|
||||
{
|
||||
serialize_newline(str);
|
||||
serialize(str, x.values_);
|
||||
}
|
||||
|
||||
} // namespace genesys
|
||||
|
||||
#endif // BACKEND_GENESYS_VALUE_FILTER_H
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
# gt68xx.conf: Configuration file for GT68XX based scanners (@PACKAGEVERSION@)
|
||||
# gt68xx.conf: Configuration file for GT68XX based scanners
|
||||
# Read man sane-gt68xx for documentation
|
||||
|
||||
# Put the firmware file into "@DATADIR@/sane/gt68xx/".
|
||||
|
|
|
@ -97,7 +97,7 @@ gt68xx_calibrator_new (SANE_Int width,
|
|||
cal->white_line = (double *) malloc (width * sizeof (double));
|
||||
cal->black_line = (double *) malloc (width * sizeof (double));
|
||||
|
||||
if (!cal->k_white || !cal->k_black | !cal->white_line || !cal->black_line)
|
||||
if (!cal->k_white || !cal->k_black || !cal->white_line || !cal->black_line)
|
||||
{
|
||||
DBG (5, "gt68xx_calibrator_new: no memory for calibration data\n");
|
||||
gt68xx_calibrator_free (cal);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Ładowanie…
Reference in New Issue