kopia lustrzana https://gitlab.com/sane-project/backends
Merge branch 'master' of https://gitlab.com/sane-project/backends into newyearsbranch
resolve po/POTFILES.inmerge-requests/213/head^2
commit
04fc970b2e
4
AUTHORS
4
AUTHORS
|
@ -1,7 +1,3 @@
|
|||
Authors of the SANE standard:
|
||||
|
||||
Andreas Beck and David Mosberger
|
||||
|
||||
Backends:
|
||||
|
||||
abaton: David Huggins-Daines
|
||||
|
|
|
@ -22,6 +22,9 @@ $ make install
|
|||
- libusb-1.0.0-dev or similar
|
||||
- libjpeg-dev or libjpeg8-dev or libjpeg-turbo-devel or turbojpeg-devel
|
||||
- libpng-dev or similar
|
||||
- libcurl4-gnutls-dev or similar
|
||||
- libxml2-dev or similar
|
||||
- libsnmp-dev or similar
|
||||
|
||||
2.2. Get the latest SANE backend from git:
|
||||
You can download "daily git snapshot" from here:
|
||||
|
|
3
LICENSE
3
LICENSE
|
@ -30,6 +30,9 @@ terms:
|
|||
to implement SANE interface conforming applications or libraries in
|
||||
any way he or she sees fit.
|
||||
|
||||
The standard is maintained at https://gitlab.com/sane-project/standard
|
||||
and published at https://sane-project.gitlab.io/standard/.
|
||||
|
||||
Frequently Asked Questions about the SANE licensing:
|
||||
|
||||
* Why don't you use the GNU LPGL ?
|
||||
|
|
50
NEWS
50
NEWS
|
@ -1,5 +1,55 @@
|
|||
<!-- -*- Mode: markdown -*- -->
|
||||
|
||||
## New with the next release
|
||||
|
||||
### Documentation
|
||||
|
||||
- removes the SANE Standard. This is now maintained as a separate
|
||||
project at https://gitlab.com/sane-project/standard. HTML and PDF
|
||||
versions can be found at https://sane-project.gitlab.io/standard/.
|
||||
|
||||
### Build
|
||||
|
||||
- removes the `--with-api-spec` option from `configure`
|
||||
|
||||
|
||||
## New with 1.0.29 (released 2020-02-02)
|
||||
|
||||
### Backends
|
||||
|
||||
- adds an `escl` backend (theoretically supporting *all* AirPrint
|
||||
devices with a scan unit)
|
||||
- adds support for 23 new scanner models via existing backends
|
||||
- significantly changes `genesys` and `pixma` backends
|
||||
- fixes bugs in `canon_dr`, `fujitsu`, `hp3900`, `mustek_usb2`,
|
||||
`plustek` and `xerox_mfp` backends
|
||||
- fixes *all* compiler warnings on Debian 10 (#120)
|
||||
- fixes portability issues for uClibc-ng and MacOS builds
|
||||
- adds support to record and replay USB I/O traffic
|
||||
- adds timestamps to debug logs
|
||||
|
||||
### Frontends
|
||||
|
||||
- fixes a 32-bit arithmetic overflow issue in `scanimage`
|
||||
|
||||
### Documentation
|
||||
|
||||
- updates translations for British English, Catalan, German,
|
||||
Ukrainian, Valencian
|
||||
- adds `scangearmp2` external backend descriptions
|
||||
- updates `hpaio` and `utsushi` external backend descriptions
|
||||
- adds the `ChangeLogs/` directory to the source tarball (#103)
|
||||
|
||||
### Build
|
||||
|
||||
- additionally requires `libcurl` and `libxml2` to build the `escl`
|
||||
backend
|
||||
- requires `libxml2` for USB I/O recording and replay functionality
|
||||
- re-enables pthread support for backends that use its API directly,
|
||||
irrespective of the `pthread_t` type (#153)
|
||||
- moves the `genesys` and `pixma` backends to a directory of their own
|
||||
|
||||
|
||||
## New with 1.0.28 (released 2019-07-31)
|
||||
|
||||
### Backends
|
||||
|
|
17
acinclude.m4
17
acinclude.m4
|
@ -252,21 +252,22 @@ AC_DEFUN([SANE_CHECK_PTHREAD],
|
|||
[Define if pthread_t is integer.])
|
||||
else
|
||||
# Until the sanei_thread implementation is fixed.
|
||||
have_pthread=no
|
||||
use_pthread=no
|
||||
fi
|
||||
|
||||
if test $use_pthread = yes ; then
|
||||
AC_DEFINE_UNQUOTED(USE_PTHREAD, "$use_pthread",
|
||||
[Define if pthreads should be used instead of forked processes.])
|
||||
else
|
||||
dnl Reset library in case it was found but we are not going to use it.
|
||||
PTHREAD_LIBS=""
|
||||
fi
|
||||
if test "$have_pthread" = "yes" ; then
|
||||
AM_CPPFLAGS="${AM_CPPFLAGS} -D_REENTRANT"
|
||||
fi
|
||||
AC_SUBST(PTHREAD_LIBS)
|
||||
|
||||
if test $use_pthread = yes ; then
|
||||
AC_DEFINE_UNQUOTED(USE_PTHREAD, "$use_pthread",
|
||||
[Define if pthreads should be used instead of forked processes.])
|
||||
SANEI_THREAD_LIBS=$PTHREAD_LIBS
|
||||
else
|
||||
SANEI_THREAD_LIBS=""
|
||||
fi
|
||||
AC_SUBST(SANEI_THREAD_LIBS)
|
||||
AC_MSG_CHECKING([whether to enable pthread support])
|
||||
AC_MSG_RESULT([$have_pthread])
|
||||
AC_MSG_CHECKING([whether to use pthread instead of fork])
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
*-s.c
|
||||
*-s.cc
|
||||
*-s.cpp
|
||||
*.conf
|
||||
.dirstamp
|
||||
dll-preload.c
|
||||
dll-preload.h
|
||||
|
|
|
@ -260,7 +260,7 @@ libagfafocus_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=agfafocus
|
|||
nodist_libsane_agfafocus_la_SOURCES = agfafocus-s.c
|
||||
libsane_agfafocus_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=agfafocus
|
||||
libsane_agfafocus_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_agfafocus_la_LIBADD = $(COMMON_LIBS) libagfafocus.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
|
||||
libsane_agfafocus_la_LIBADD = $(COMMON_LIBS) libagfafocus.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += agfafocus.conf.in
|
||||
|
||||
libapple_la_SOURCES = apple.c apple.h
|
||||
|
@ -287,7 +287,7 @@ libartec_eplus48u_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=artec_eplus48u
|
|||
nodist_libsane_artec_eplus48u_la_SOURCES = artec_eplus48u-s.c
|
||||
libsane_artec_eplus48u_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=artec_eplus48u
|
||||
libsane_artec_eplus48u_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_artec_eplus48u_la_LIBADD = $(COMMON_LIBS) libartec_eplus48u.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 $(MATH_LIB) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMEG_LIBS)
|
||||
libsane_artec_eplus48u_la_LIBADD = $(COMMON_LIBS) libartec_eplus48u.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 $(MATH_LIB) $(USB_LIBS) $(SANEI_THREAD_LIBS) $(RESMEG_LIBS)
|
||||
EXTRA_DIST += artec_eplus48u.conf.in
|
||||
|
||||
libas6e_la_SOURCES = as6e.c as6e.h
|
||||
|
@ -304,7 +304,7 @@ libavision_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=avision
|
|||
nodist_libsane_avision_la_SOURCES = avision-s.c
|
||||
libsane_avision_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=avision
|
||||
libsane_avision_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_avision_la_LIBADD = $(COMMON_LIBS) libavision.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_thread.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
|
||||
libsane_avision_la_LIBADD = $(COMMON_LIBS) libavision.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_thread.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += avision.conf.in
|
||||
|
||||
libbh_la_SOURCES = bh.c bh.h
|
||||
|
@ -382,7 +382,7 @@ libcoolscan_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=coolscan
|
|||
nodist_libsane_coolscan_la_SOURCES = coolscan-s.c
|
||||
libsane_coolscan_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=coolscan
|
||||
libsane_coolscan_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_coolscan_la_LIBADD = $(COMMON_LIBS) libcoolscan.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_thread.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
|
||||
libsane_coolscan_la_LIBADD = $(COMMON_LIBS) libcoolscan.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_thread.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += coolscan.conf.in
|
||||
|
||||
libcoolscan2_la_SOURCES = coolscan2.c
|
||||
|
@ -451,13 +451,13 @@ EXTRA_DIST += dmc.conf.in
|
|||
if have_libavahi
|
||||
if have_libcurl
|
||||
if have_libxml2
|
||||
libescl_la_SOURCES = escl/escl.c escl/escl_capabilities.c escl/escl_devices.c escl/escl.h escl/escl_newjob.c escl/escl_reset.c escl/escl_scan.c escl/escl_status.c
|
||||
libescl_la_CPPFLAGS = $(AM_CPPFLAGS) $(JPEG_CFLAGS) $(XML_CFLAGS) $(libcurl_CFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=escl
|
||||
libescl_la_SOURCES = escl/escl.c escl/escl_capabilities.c escl/escl_devices.c escl/escl.h escl/escl_newjob.c escl/escl_reset.c escl/escl_scan.c escl/escl_status.c escl/escl_jpeg.c escl/escl_png.c escl/escl_tiff.c escl/escl_crop.c
|
||||
libescl_la_CPPFLAGS = $(AM_CPPFLAGS) $(JPEG_CFLAGS) $(PNG_CFLAGS) $(TIFF_CFLAGS) $(XML_CFLAGS) $(libcurl_CFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=escl
|
||||
|
||||
nodist_libsane_escl_la_SOURCES = escl-s.c
|
||||
libsane_escl_la_CPPFLAGS = $(AM_CPPFLAGS) $(JPEG_CFLAGS) $(XML_CFLAGS) $(libcurl_CFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=escl
|
||||
libsane_escl_la_CPPFLAGS = $(AM_CPPFLAGS) $(JPEG_CFLAGS) $(PNG_CFLAGS) $(TIFF_CFLAGS) $(XML_CFLAGS) $(libcurl_CFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=escl
|
||||
libsane_escl_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_escl_la_LIBADD = $(COMMON_LIBS) libescl.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(JPEG_LIBS) $(XML_LIBS) $(libcurl_LIBS) $(AVAHI_LIBS)
|
||||
libsane_escl_la_LIBADD = $(COMMON_LIBS) libescl.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(MATH_LIB) $(JPEG_LIBS) $(PNG_LIBS) $(TIFF_LIBS) $(XML_LIBS) $(libcurl_LIBS) $(AVAHI_LIBS)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
@ -518,6 +518,7 @@ libgenesys_la_SOURCES = genesys/genesys.cpp genesys/genesys.h \
|
|||
genesys/buffer.h genesys/buffer.cpp \
|
||||
genesys/calibration.h \
|
||||
genesys/command_set.h \
|
||||
genesys/command_set_common.h genesys/command_set_common.cpp \
|
||||
genesys/conv.h genesys/conv.cpp \
|
||||
genesys/device.h genesys/device.cpp \
|
||||
genesys/enums.h genesys/enums.cpp \
|
||||
|
@ -548,7 +549,6 @@ libgenesys_la_SOURCES = genesys/genesys.cpp genesys/genesys.h \
|
|||
genesys/tables_gpo.cpp \
|
||||
genesys/tables_model.cpp \
|
||||
genesys/tables_motor.cpp \
|
||||
genesys/tables_motor_profile.cpp \
|
||||
genesys/tables_sensor.cpp \
|
||||
genesys/test_scanner_interface.h genesys/test_scanner_interface.cpp \
|
||||
genesys/test_settings.h genesys/test_settings.cpp \
|
||||
|
@ -591,7 +591,7 @@ libhp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp
|
|||
nodist_libsane_hp_la_SOURCES = hp-s.c
|
||||
libsane_hp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp
|
||||
libsane_hp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_hp_la_LIBADD = $(COMMON_LIBS) libhp.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_pio.lo ../sanei/sanei_thread.lo $(SCSI_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
|
||||
libsane_hp_la_LIBADD = $(COMMON_LIBS) libhp.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_pio.lo ../sanei/sanei_thread.lo $(SCSI_LIBS) $(USB_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += hp.conf.in
|
||||
# TODO: These should be moved to ../docs/hp; don't belong here.
|
||||
EXTRA_DIST += hp.README hp.TODO
|
||||
|
@ -602,7 +602,7 @@ libhp3500_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp3500
|
|||
nodist_libsane_hp3500_la_SOURCES = hp3500-s.c
|
||||
libsane_hp3500_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp3500
|
||||
libsane_hp3500_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_hp3500_la_LIBADD = $(COMMON_LIBS) libhp3500.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 $(MATH_LIB) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
|
||||
libsane_hp3500_la_LIBADD = $(COMMON_LIBS) libhp3500.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 $(MATH_LIB) $(USB_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS)
|
||||
|
||||
libhp3900_la_SOURCES = hp3900.c
|
||||
libhp3900_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp3900
|
||||
|
@ -794,7 +794,7 @@ libmicrotek2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=microtek2
|
|||
nodist_libsane_microtek2_la_SOURCES = microtek2-s.c
|
||||
libsane_microtek2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=microtek2
|
||||
libsane_microtek2_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_microtek2_la_LIBADD = $(COMMON_LIBS) libmicrotek2.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
|
||||
libsane_microtek2_la_LIBADD = $(COMMON_LIBS) libmicrotek2.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(SCSI_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += microtek2.conf.in
|
||||
|
||||
libmustek_la_SOURCES = mustek.c mustek.h
|
||||
|
@ -803,7 +803,7 @@ libmustek_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek
|
|||
nodist_libsane_mustek_la_SOURCES = mustek-s.c
|
||||
libsane_mustek_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek
|
||||
libsane_mustek_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_mustek_la_LIBADD = $(COMMON_LIBS) libmustek.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo ../sanei/sanei_ab306.lo ../sanei/sanei_pa4s2.lo $(IEEE1284_LIBS) $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
|
||||
libsane_mustek_la_LIBADD = $(COMMON_LIBS) libmustek.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo ../sanei/sanei_ab306.lo ../sanei/sanei_pa4s2.lo $(IEEE1284_LIBS) $(SCSI_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += mustek.conf.in
|
||||
# TODO: Why are these distributed but not compiled?
|
||||
EXTRA_DIST += mustek_scsi_pp.c mustek_scsi_pp.h
|
||||
|
@ -836,7 +836,7 @@ libmustek_usb2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek_usb2
|
|||
nodist_libsane_mustek_usb2_la_SOURCES = mustek_usb2-s.c
|
||||
libsane_mustek_usb2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek_usb2
|
||||
libsane_mustek_usb2_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_mustek_usb2_la_LIBADD = $(COMMON_LIBS) libmustek_usb2.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 $(MATH_LIB) $(PTHREAD_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
|
||||
libsane_mustek_usb2_la_LIBADD = $(COMMON_LIBS) libmustek_usb2.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(PTHREAD_LIBS) $(USB_LIBS) $(RESMGR_LIBS)
|
||||
# TODO: Why are these distributed but not compiled?
|
||||
EXTRA_DIST += mustek_usb2_asic.c mustek_usb2_asic.h mustek_usb2_high.c mustek_usb2_high.h mustek_usb2_reflective.c mustek_usb2_transparent.c
|
||||
|
||||
|
@ -874,7 +874,7 @@ libpie_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pie
|
|||
nodist_libsane_pie_la_SOURCES = pie-s.c
|
||||
libsane_pie_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pie
|
||||
libsane_pie_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_pie_la_LIBADD = $(COMMON_LIBS) libpie.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
|
||||
libsane_pie_la_LIBADD = $(COMMON_LIBS) libpie.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo $(SCSI_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += pie.conf.in
|
||||
|
||||
libpieusb_la_SOURCES = pieusb.h pieusb_buffer.c pieusb_buffer.h pieusb_scancmd.c pieusb_scancmd.h pieusb_specific.c pieusb_specific.h pieusb_usb.c pieusb_usb.h pieusb.c
|
||||
|
@ -883,7 +883,7 @@ libpieusb_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pieusb
|
|||
nodist_libsane_pieusb_la_SOURCES = pieusb-s.c
|
||||
libsane_pieusb_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pieusb
|
||||
libsane_pieusb_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_pieusb_la_LIBADD = $(COMMON_LIBS) libpieusb.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo ../sanei/sanei_usb.lo ../sanei/sanei_ir.lo ../sanei/sanei_magic.lo $(PTHREAD_LIBS) $(RESMGR_LIBS) $(USB_LIBS) $(MATH_LIB)
|
||||
libsane_pieusb_la_LIBADD = $(COMMON_LIBS) libpieusb.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo ../sanei/sanei_usb.lo ../sanei/sanei_ir.lo ../sanei/sanei_magic.lo $(SANEI_THREAD_LIBS) $(RESMGR_LIBS) $(USB_LIBS) $(MATH_LIB)
|
||||
EXTRA_DIST += pieusb.conf.in
|
||||
|
||||
libp5_la_SOURCES = p5.c p5.h p5_device.h
|
||||
|
@ -903,16 +903,30 @@ libsane_pint_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pint
|
|||
libsane_pint_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_pint_la_LIBADD = $(COMMON_LIBS) libpint.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo
|
||||
|
||||
libpixma_la_SOURCES = pixma.c pixma.h pixma_io_sanei.c pixma_io.h pixma_common.c pixma_common.h pixma_mp150.c pixma_mp730.c pixma_mp750.c pixma_mp800.c pixma_imageclass.c pixma_bjnp.c pixma_bjnp.h pixma_bjnp_private.h pixma_rename.h
|
||||
libpixma_la_SOURCES = pixma/pixma.c \
|
||||
pixma/pixma.h \
|
||||
pixma/pixma_io_sanei.c \
|
||||
pixma/pixma_io.h \
|
||||
pixma/pixma_common.c \
|
||||
pixma/pixma_common.h \
|
||||
pixma/pixma_mp150.c \
|
||||
pixma/pixma_mp730.c \
|
||||
pixma/pixma_mp750.c \
|
||||
pixma/pixma_mp800.c \
|
||||
pixma/pixma_imageclass.c \
|
||||
pixma/pixma_bjnp.c \
|
||||
pixma/pixma_bjnp.h \
|
||||
pixma/pixma_bjnp_private.h \
|
||||
pixma/pixma_rename.h
|
||||
libpixma_la_CPPFLAGS = $(AM_CPPFLAGS) -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) $(PTHREAD_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) $(MATH_LIB) $(SOCKET_LIBS) $(USB_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += pixma.conf.in
|
||||
# TODO: Why are these distributed but not compiled?
|
||||
EXTRA_DIST += pixma_sane_options.c pixma_sane_options.h
|
||||
# included in pixma.c
|
||||
EXTRA_DIST += pixma/pixma_sane_options.c pixma/pixma_sane_options.h
|
||||
|
||||
libplustek_la_SOURCES = plustek.c plustek.h
|
||||
libplustek_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=plustek
|
||||
|
@ -920,7 +934,7 @@ libplustek_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=plustek
|
|||
nodist_libsane_plustek_la_SOURCES = plustek-s.c
|
||||
libsane_plustek_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=plustek
|
||||
libsane_plustek_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_plustek_la_LIBADD = $(COMMON_LIBS) libplustek.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_lm983x.lo ../sanei/sanei_access.lo $(MATH_LIB) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
|
||||
libsane_plustek_la_LIBADD = $(COMMON_LIBS) libplustek.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_lm983x.lo ../sanei/sanei_access.lo $(MATH_LIB) $(USB_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += plustek.conf.in
|
||||
EXTRA_DIST += plustek-usb.c plustek-usb.h plustek-usbcal.c plustek-usbcalfile.c plustek-usbdevs.c plustek-usbhw.c plustek-usbimg.c plustek-usbio.c plustek-usbmap.c plustek-usbscan.c plustek-usbshading.c
|
||||
|
||||
|
@ -930,7 +944,7 @@ libplustek_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=plustek_pp
|
|||
nodist_libsane_plustek_pp_la_SOURCES = plustek_pp-s.c
|
||||
libsane_plustek_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=plustek_pp
|
||||
libsane_plustek_pp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_plustek_pp_la_LIBADD = $(COMMON_LIBS) libplustek_pp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_pp.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(IEEE1284_LIBS) $(PTHREAD_LIBS)
|
||||
libsane_plustek_pp_la_LIBADD = $(COMMON_LIBS) libplustek_pp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_pp.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(IEEE1284_LIBS) $(SANEI_THREAD_LIBS)
|
||||
EXTRA_DIST += plustek_pp.conf.in
|
||||
# TODO: Why are these distributed but not compiled?
|
||||
EXTRA_DIST += plustek-pp_dac.c plustek-pp_dbg.h plustek-pp_detect.c plustek-pp_genericio.c plustek-pp_hwdefs.h plustek-pp_image.c plustek-pp_io.c plustek-pp_map.c plustek-pp_misc.c plustek-pp_models.c plustek-pp_motor.c plustek-pp_p12.c plustek-pp_p12ccd.c plustek-pp_p48xx.c plustek-pp_p9636.c plustek-pp_procfs.c plustek-pp_procs.h plustek-pp_ptdrv.c plustek-pp_scale.c plustek-pp_scan.h plustek-pp_scandata.h plustek-pp_sysdep.h plustek-pp_tpa.c plustek-pp_types.h plustek-pp_wrapper.c
|
||||
|
@ -1037,7 +1051,7 @@ libsnapscan_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=snapscan
|
|||
nodist_libsane_snapscan_la_SOURCES = snapscan-s.c
|
||||
libsane_snapscan_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=snapscan
|
||||
libsane_snapscan_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_snapscan_la_LIBADD = $(COMMON_LIBS) libsnapscan.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_thread.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
|
||||
libsane_snapscan_la_LIBADD = $(COMMON_LIBS) libsnapscan.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_thread.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += snapscan.conf.in
|
||||
# TODO: Why are these distributed but not compiled?
|
||||
EXTRA_DIST += snapscan-data.c snapscan-mutex.c snapscan-options.c snapscan-scsi.c snapscan-sources.c snapscan-sources.h snapscan-usb.c snapscan-usb.h
|
||||
|
@ -1048,7 +1062,7 @@ libsp15c_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sp15c
|
|||
nodist_libsane_sp15c_la_SOURCES = sp15c-s.c
|
||||
libsane_sp15c_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sp15c
|
||||
libsane_sp15c_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_sp15c_la_LIBADD = $(COMMON_LIBS) libsp15c.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
|
||||
libsane_sp15c_la_LIBADD = $(COMMON_LIBS) libsp15c.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += sp15c.conf.in
|
||||
|
||||
libst400_la_SOURCES = st400.c st400.h
|
||||
|
@ -1075,7 +1089,7 @@ libtamarack_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=tamarack
|
|||
nodist_libsane_tamarack_la_SOURCES = tamarack-s.c
|
||||
libsane_tamarack_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=tamarack
|
||||
libsane_tamarack_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_tamarack_la_LIBADD = $(COMMON_LIBS) libtamarack.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
|
||||
libsane_tamarack_la_LIBADD = $(COMMON_LIBS) libtamarack.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += tamarack.conf.in
|
||||
|
||||
libtest_la_SOURCES = test.c test.h
|
||||
|
@ -1084,7 +1098,7 @@ libtest_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=test
|
|||
nodist_libsane_test_la_SOURCES = test-s.c
|
||||
libsane_test_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=test
|
||||
libsane_test_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_test_la_LIBADD = $(COMMON_LIBS) libtest.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_thread.lo $(PTHREAD_LIBS)
|
||||
libsane_test_la_LIBADD = $(COMMON_LIBS) libtest.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_thread.lo $(SANEI_THREAD_LIBS)
|
||||
EXTRA_DIST += test.conf.in
|
||||
# TODO: Why are these distributed but not compiled?
|
||||
EXTRA_DIST += test-picture.c
|
||||
|
@ -1122,7 +1136,7 @@ libu12_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=u12
|
|||
nodist_libsane_u12_la_SOURCES = u12-s.c
|
||||
libsane_u12_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=u12
|
||||
libsane_u12_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_u12_la_LIBADD = $(COMMON_LIBS) libu12.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 $(MATH_LIB) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
|
||||
libsane_u12_la_LIBADD = $(COMMON_LIBS) libu12.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 $(MATH_LIB) $(USB_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += u12.conf.in
|
||||
# TODO: Why are these distributed but not compiled?
|
||||
EXTRA_DIST += u12-ccd.c u12-hw.c u12-hwdef.h u12-if.c u12-image.c u12-io.c u12-map.c u12-motor.c u12-scanner.h u12-shading.c u12-tpa.c
|
||||
|
@ -1133,7 +1147,7 @@ libumax_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=umax
|
|||
nodist_libsane_umax_la_SOURCES = umax-s.c
|
||||
libsane_umax_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=umax
|
||||
libsane_umax_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
|
||||
libsane_umax_la_LIBADD = $(COMMON_LIBS) libumax.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_thread.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pv8630.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS)
|
||||
libsane_umax_la_LIBADD = $(COMMON_LIBS) libumax.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_thread.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pv8630.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS)
|
||||
EXTRA_DIST += umax.conf.in
|
||||
# TODO: Why are these distributed but not compiled?
|
||||
EXTRA_DIST += umax-scanner.c umax-scanner.h umax-scsidef.h umax-uc1200s.c umax-uc1200se.c umax-uc1260.c umax-uc630.c umax-uc840.c umax-ug630.c umax-ug80.c umax-usb.c
|
||||
|
@ -1212,7 +1226,7 @@ EXTRA_DIST += dll.aliases
|
|||
# what backends are preloaded. It should include what is needed by
|
||||
# those backends that are actually preloaded.
|
||||
if preloadable_backends_enabled
|
||||
PRELOADABLE_BACKENDS_LIBS = ../sanei/sanei_config2.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pv8630.lo ../sanei/sanei_pp.lo ../sanei/sanei_thread.lo ../sanei/sanei_lm983x.lo ../sanei/sanei_access.lo ../sanei/sanei_net.lo ../sanei/sanei_wire.lo ../sanei/sanei_codec_bin.lo ../sanei/sanei_pa4s2.lo ../sanei/sanei_ab306.lo ../sanei/sanei_pio.lo ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo ../sanei/sanei_magic.lo $(LIBV4L_LIBS) $(MATH_LIB) $(IEEE1284_LIBS) $(TIFF_LIBS) $(JPEG_LIBS) $(GPHOTO2_LIBS) $(SOCKET_LIBS) $(USB_LIBS) $(AVAHI_LIBS) $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) $(XML_LIBS)
|
||||
PRELOADABLE_BACKENDS_LIBS = ../sanei/sanei_config2.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pv8630.lo ../sanei/sanei_pp.lo ../sanei/sanei_thread.lo ../sanei/sanei_lm983x.lo ../sanei/sanei_access.lo ../sanei/sanei_net.lo ../sanei/sanei_wire.lo ../sanei/sanei_codec_bin.lo ../sanei/sanei_pa4s2.lo ../sanei/sanei_ab306.lo ../sanei/sanei_pio.lo ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo ../sanei/sanei_magic.lo $(LIBV4L_LIBS) $(MATH_LIB) $(IEEE1284_LIBS) $(TIFF_LIBS) $(JPEG_LIBS) $(GPHOTO2_LIBS) $(SOCKET_LIBS) $(USB_LIBS) $(AVAHI_LIBS) $(SCSI_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS) $(XML_LIBS)
|
||||
PRELOADABLE_BACKENDS_DEPS = ../sanei/sanei_config2.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pv8630.lo ../sanei/sanei_pp.lo ../sanei/sanei_thread.lo ../sanei/sanei_lm983x.lo ../sanei/sanei_access.lo ../sanei/sanei_net.lo ../sanei/sanei_wire.lo ../sanei/sanei_codec_bin.lo ../sanei/sanei_pa4s2.lo ../sanei/sanei_ab306.lo ../sanei/sanei_pio.lo ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo ../sanei/sanei_magic.lo $(SANEI_SANEI_JPEG_LO)
|
||||
endif
|
||||
nodist_libsane_la_SOURCES = dll-s.c
|
||||
|
@ -1221,4 +1235,4 @@ libsane_la_LDFLAGS = $(DIST_LIBS_LDFLAGS)
|
|||
libsane_la_LIBADD = $(COMMON_LIBS) $(PRELOADABLE_BACKENDS_ENABLED) libdll_preload.la sane_strstatus.lo ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo $(PRELOADABLE_BACKENDS_LIBS) $(DL_LIBS) $(XML_LIBS)
|
||||
|
||||
# WARNING: Automake is getting this wrong so have to do it ourselves.
|
||||
libsane_la_DEPENDENCIES = $(COMMON_LIBS) $(PRELOADABLE_BACKENDS_ENABLED) libdll_preload.la sane_strstatus.lo ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo $(PRELOADABLE_BACKENDS_DEPS)
|
||||
libsane_la_DEPENDENCIES = ../lib/liblib.la $(PRELOADABLE_BACKENDS_ENABLED) libdll_preload.la sane_strstatus.lo ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo $(PRELOADABLE_BACKENDS_DEPS)
|
||||
|
|
|
@ -4088,6 +4088,8 @@ get_double ( &(result[48] ) ));
|
|||
dev->inquiry_button_control = BIT (result[50], 6) | BIT (result[51],2);
|
||||
|
||||
dev->inquiry_exposure_control = BIT(result[51],7);
|
||||
if (dev->scanner_type != AV_FILM && !(dev->hw->feature_type & AV_FORCE_FILM))
|
||||
dev->inquiry_exposure_control = 0;
|
||||
dev->inquiry_max_shading_target = get_double ( &(result[75]) );
|
||||
|
||||
dev->inquiry_color_boundary = result[54];
|
||||
|
@ -6221,7 +6223,12 @@ do_cancel (Avision_Scanner* s)
|
|||
s->prepared = s->scanning = SANE_FALSE;
|
||||
s->duplex_rear_valid = SANE_FALSE;
|
||||
s->page = 0;
|
||||
s->cancelled = 1;
|
||||
s->cancelled = SANE_TRUE;
|
||||
|
||||
if (s->read_fds >= 0) {
|
||||
close(s->read_fds);
|
||||
s->read_fds = -1;
|
||||
}
|
||||
|
||||
if (sanei_thread_is_valid (s->reader_pid)) {
|
||||
int exit_status;
|
||||
|
@ -6716,6 +6723,7 @@ reader_process (void *data)
|
|||
sigset_t sigterm_set;
|
||||
sigset_t ignore_set;
|
||||
struct SIGACTION act;
|
||||
int old;
|
||||
|
||||
FILE* fp;
|
||||
FILE* rear_fp = 0; /* used to store the deinterlaced rear data */
|
||||
|
@ -6757,21 +6765,30 @@ reader_process (void *data)
|
|||
|
||||
DBG (3, "reader_process:\n");
|
||||
|
||||
if (sanei_thread_is_forked())
|
||||
if (sanei_thread_is_forked()) {
|
||||
close (s->read_fds);
|
||||
s->read_fds = -1;
|
||||
|
||||
sigfillset (&ignore_set);
|
||||
sigdelset (&ignore_set, SIGTERM);
|
||||
sigfillset (&ignore_set);
|
||||
sigdelset (&ignore_set, SIGTERM);
|
||||
#if defined (__APPLE__) && defined (__MACH__)
|
||||
sigdelset (&ignore_set, SIGUSR2);
|
||||
sigdelset (&ignore_set, SIGUSR2);
|
||||
#endif
|
||||
sigprocmask (SIG_SETMASK, &ignore_set, 0);
|
||||
sigprocmask (SIG_SETMASK, &ignore_set, 0);
|
||||
|
||||
memset (&act, 0, sizeof (act));
|
||||
sigaction (SIGTERM, &act, 0);
|
||||
memset (&act, 0, sizeof (act));
|
||||
sigaction (SIGTERM, &act, 0);
|
||||
|
||||
sigemptyset (&sigterm_set);
|
||||
sigaddset (&sigterm_set, SIGTERM);
|
||||
sigemptyset (&sigterm_set);
|
||||
sigaddset (&sigterm_set, SIGTERM);
|
||||
}
|
||||
#ifdef USE_PTHREAD
|
||||
else {
|
||||
int old;
|
||||
pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &old);
|
||||
pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
|
||||
}
|
||||
#endif
|
||||
|
||||
gray_mode = color_mode_is_shaded (s->c_mode);
|
||||
|
||||
|
@ -6958,9 +6975,22 @@ reader_process (void *data)
|
|||
(u_long) processed_bytes, (u_long) total_size);
|
||||
DBG (5, "reader_process: this_read: %lu\n", (u_long) this_read);
|
||||
|
||||
sigprocmask (SIG_BLOCK, &sigterm_set, 0);
|
||||
if (sanei_thread_is_forked())
|
||||
sigprocmask (SIG_BLOCK, &sigterm_set, 0);
|
||||
#ifdef USE_PTHREAD
|
||||
else
|
||||
pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &old);
|
||||
#endif
|
||||
|
||||
status = read_data (s, stripe_data + stripe_fill, &this_read);
|
||||
sigprocmask (SIG_UNBLOCK, &sigterm_set, 0);
|
||||
|
||||
if (sanei_thread_is_forked())
|
||||
sigprocmask (SIG_UNBLOCK, &sigterm_set, 0);
|
||||
#ifdef USE_PTHREAD
|
||||
else
|
||||
pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &old);
|
||||
#endif
|
||||
|
||||
|
||||
/* only EOF on the second stripe, as otherwise the rear page
|
||||
is shorter */
|
||||
|
@ -8332,7 +8362,7 @@ sane_start (SANE_Handle handle)
|
|||
return SANE_STATUS_DEVICE_BUSY;
|
||||
|
||||
/* Clear cancellation status */
|
||||
s->cancelled = 0;
|
||||
s->cancelled = SANE_FALSE;
|
||||
|
||||
/* Make sure we have a current parameter set. Some of the
|
||||
parameters will be overwritten below, but that's OK. */
|
||||
|
@ -8560,8 +8590,10 @@ sane_start (SANE_Handle handle)
|
|||
DBG (3, "sane_start: starting thread\n");
|
||||
s->reader_pid = sanei_thread_begin (reader_process, (void *) s);
|
||||
|
||||
if (sanei_thread_is_forked())
|
||||
close (s->write_fds);
|
||||
if (sanei_thread_is_forked()) {
|
||||
close (s->write_fds);
|
||||
s->write_fds = -1;
|
||||
}
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
|
||||
|
|
|
@ -11,10 +11,10 @@ net
|
|||
abaton
|
||||
agfafocus
|
||||
apple
|
||||
avision
|
||||
artec
|
||||
artec_eplus48u
|
||||
as6e
|
||||
avision
|
||||
bh
|
||||
canon
|
||||
canon630u
|
||||
|
@ -25,33 +25,35 @@ cardscan
|
|||
coolscan
|
||||
#coolscan2
|
||||
coolscan3
|
||||
#dc25
|
||||
#dc210
|
||||
#dc240
|
||||
#dc25
|
||||
dell1600n_net
|
||||
dmc
|
||||
epjitsu
|
||||
#epson
|
||||
epson2
|
||||
epsonds
|
||||
escl
|
||||
fujitsu
|
||||
#gphoto2
|
||||
genesys
|
||||
#gphoto2
|
||||
gt68xx
|
||||
hp
|
||||
hp3900
|
||||
hpsj5s
|
||||
hp3500
|
||||
hp3900
|
||||
hp4200
|
||||
hp5400
|
||||
hp5590
|
||||
hpljm1005
|
||||
hpsj5s
|
||||
hs2p
|
||||
ibm
|
||||
kodak
|
||||
kodakaio
|
||||
kvs1025
|
||||
kvs20xx
|
||||
kvs40xx
|
||||
leo
|
||||
lexmark
|
||||
ma1509
|
||||
|
@ -67,6 +69,7 @@ nec
|
|||
niash
|
||||
#p5
|
||||
pie
|
||||
pieusb
|
||||
pint
|
||||
pixma
|
||||
plustek
|
||||
|
@ -92,7 +95,7 @@ teco3
|
|||
#test
|
||||
u12
|
||||
umax
|
||||
#umax_pp
|
||||
umax1220u
|
||||
#umax_pp
|
||||
v4l
|
||||
xerox_mfp
|
||||
|
|
|
@ -27,14 +27,14 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <jpeglib.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "../include/sane/saneopts.h"
|
||||
#include "../include/sane/sanei.h"
|
||||
#include "../include/sane/sanei_backend.h"
|
||||
#include "../include/sane/sanei_config.h"
|
||||
#include "../include/sane/sanei_debug.h"
|
||||
|
||||
#define min(A,B) (((A)<(B)) ? (A) : (B))
|
||||
#define max(A,B) (((A)>(B)) ? (A) : (B))
|
||||
|
@ -54,9 +54,6 @@ typedef struct Handled {
|
|||
capabilities_t *scanner;
|
||||
SANE_Range x_range;
|
||||
SANE_Range y_range;
|
||||
unsigned char *img_data;
|
||||
long img_size;
|
||||
long img_read;
|
||||
SANE_Bool cancel;
|
||||
SANE_Bool write_scan_data;
|
||||
SANE_Bool decompress_scan_data;
|
||||
|
@ -64,18 +61,45 @@ typedef struct Handled {
|
|||
SANE_Parameters ps;
|
||||
} escl_sane_t;
|
||||
|
||||
struct my_error_mgr
|
||||
static ESCL_Device *
|
||||
escl_free_device(ESCL_Device *current)
|
||||
{
|
||||
struct jpeg_error_mgr errmgr;
|
||||
jmp_buf escape;
|
||||
};
|
||||
if (!current) return NULL;
|
||||
free((void*)current->ip_address);
|
||||
free((void*)current->model_name);
|
||||
free((void*)current->type);
|
||||
free(current);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
static SANE_Status
|
||||
escl_check_and_add_device(ESCL_Device *current)
|
||||
{
|
||||
struct jpeg_source_mgr pub;
|
||||
FILE *ctx;
|
||||
unsigned char buffer[INPUT_BUFFER_SIZE];
|
||||
} my_source_mgr;
|
||||
if(!current) {
|
||||
DBG (10, "ESCL_Device *current us null.\n");
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
if (!current->ip_address) {
|
||||
DBG (10, "Ip Address allocation failure.\n");
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
if (current->port_nb == 0) {
|
||||
DBG (10, "No port defined.\n");
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
if (!current->model_name) {
|
||||
DBG (10, "Modele Name allocation failure.\n");
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
if (!current->type) {
|
||||
DBG (10, "Scanner Type allocation failure.\n");
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
++num_devices;
|
||||
current->next = list_devices_primary;
|
||||
list_devices_primary = current;
|
||||
return (SANE_STATUS_GOOD);
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn static SANE_Status escl_add_in_list(ESCL_Device *current)
|
||||
|
@ -88,10 +112,18 @@ typedef struct
|
|||
static SANE_Status
|
||||
escl_add_in_list(ESCL_Device *current)
|
||||
{
|
||||
++num_devices;
|
||||
current->next = list_devices_primary;
|
||||
list_devices_primary = current;
|
||||
return (SANE_STATUS_GOOD);
|
||||
if(!current) {
|
||||
DBG (10, "ESCL_Device *current us null.\n");
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
|
||||
if (SANE_STATUS_GOOD ==
|
||||
escl_check_and_add_device(current)) {
|
||||
list_devices_primary = current;
|
||||
return (SANE_STATUS_GOOD);
|
||||
}
|
||||
current = escl_free_device(current);
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,6 +137,8 @@ escl_add_in_list(ESCL_Device *current)
|
|||
SANE_Status
|
||||
escl_device_add(int port_nb, const char *model_name, char *ip_address, char *type)
|
||||
{
|
||||
char tmp[PATH_MAX] = { 0 };
|
||||
char *model = NULL;
|
||||
ESCL_Device *current = NULL;
|
||||
DBG (10, "escl_device_add\n");
|
||||
for (current = list_devices_primary; current; current = current->next) {
|
||||
|
@ -112,12 +146,18 @@ escl_device_add(int port_nb, const char *model_name, char *ip_address, char *typ
|
|||
&& strcmp(current->type, type) == 0)
|
||||
return (SANE_STATUS_GOOD);
|
||||
}
|
||||
current = malloc(sizeof(*current));
|
||||
if (current == NULL)
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
memset(current, 0, sizeof(*current));
|
||||
current = (ESCL_Device*)calloc(1, sizeof(*current));
|
||||
if (current == NULL) {
|
||||
DBG (10, "New device allocation failure.\n");
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
current->port_nb = port_nb;
|
||||
current->model_name = strdup(model_name);
|
||||
|
||||
if (strcmp(type, "_uscan._tcp") != 0 && strcmp(type, "http") != 0) {
|
||||
snprintf(tmp, sizeof(tmp), "%s SSL", model_name);
|
||||
}
|
||||
model = (char*)(tmp[0] != 0 ? tmp : model_name);
|
||||
current->model_name = strdup(model);
|
||||
current->ip_address = strdup(ip_address);
|
||||
current->type = strdup(type);
|
||||
return escl_add_in_list(current);
|
||||
|
@ -158,18 +198,48 @@ max_string_size(const SANE_String_Const strings[])
|
|||
static SANE_Device *
|
||||
convertFromESCLDev(ESCL_Device *cdev)
|
||||
{
|
||||
SANE_Device *sdev = (SANE_Device*) calloc(1, sizeof(SANE_Device));
|
||||
char tmp[PATH_MAX] = { 0 };
|
||||
SANE_Device *sdev = (SANE_Device*) calloc(1, sizeof(SANE_Device));
|
||||
if (!sdev) {
|
||||
DBG (10, "Sane_Device allocation failure.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strcmp(cdev->type, "_uscan._tcp") == 0 || strcmp(cdev->type, "http") == 0)
|
||||
snprintf(tmp, sizeof(tmp), "http://%s:%d", cdev->ip_address, cdev->port_nb);
|
||||
else
|
||||
snprintf(tmp, sizeof(tmp), "https://%s:%d", cdev->ip_address, cdev->port_nb);
|
||||
DBG( 1, "Escl add device : %s\n", tmp);
|
||||
sdev->name = strdup(tmp);
|
||||
if (!sdev->name) {
|
||||
DBG (10, "Name allocation failure.\n");
|
||||
goto freedev;
|
||||
}
|
||||
sdev->model = strdup(cdev->model_name);
|
||||
if (!sdev->model) {
|
||||
DBG (10, "Model allocation failure.\n");
|
||||
goto freename;
|
||||
}
|
||||
sdev->vendor = strdup("ESCL");
|
||||
if (!sdev->vendor) {
|
||||
DBG (10, "Vendor allocation failure.\n");
|
||||
goto freemodel;
|
||||
}
|
||||
sdev->type = strdup("flatbed scanner");
|
||||
if (!sdev->type) {
|
||||
DBG (10, "Scanner Type allocation failure.\n");
|
||||
goto freevendor;
|
||||
}
|
||||
return (sdev);
|
||||
freevendor:
|
||||
free((void*)sdev->vendor);
|
||||
freemodel:
|
||||
free((void*)sdev->model);
|
||||
freename:
|
||||
free((void*)sdev->name);
|
||||
freedev:
|
||||
free((void*)sdev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -187,7 +257,7 @@ sane_init(SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize)
|
|||
DBG_INIT();
|
||||
DBG (10, "escl sane_init\n");
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
if (version_code != NULL)
|
||||
*version_code = SANE_VERSION_CODE(1, 0, 0);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
|
@ -217,6 +287,7 @@ sane_exit(void)
|
|||
free (devlist);
|
||||
list_devices_primary = NULL;
|
||||
devlist = NULL;
|
||||
curl_global_cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -232,44 +303,52 @@ static SANE_Status
|
|||
attach_one_config(SANEI_Config __sane_unused__ *config, const char *line)
|
||||
{
|
||||
int port = 0;
|
||||
static int count = 0;
|
||||
SANE_Status status;
|
||||
static ESCL_Device *escl_device = NULL;
|
||||
|
||||
if (strncmp(line, "[device]", 8) == 0) {
|
||||
count = 0;
|
||||
escl_device = escl_free_device(escl_device);
|
||||
escl_device = (ESCL_Device*)calloc(1, sizeof(ESCL_Device));
|
||||
if (!escl_device) {
|
||||
DBG (10, "New Escl_Device allocation failure.");
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
}
|
||||
if (strncmp(line, "ip", 2) == 0) {
|
||||
const char *ip_space = sanei_config_skip_whitespace(line + 2);
|
||||
DBG (10, "New Escl_Device IP [%s].", (ip_space ? ip_space : "VIDE"));
|
||||
if (escl_device != NULL && ip_space != NULL) {
|
||||
count++;
|
||||
DBG (10, "New Escl_Device IP Affected.");
|
||||
escl_device->ip_address = strdup(ip_space);
|
||||
}
|
||||
}
|
||||
if (sscanf(line, "port %i", &port) == 1 && port != 0) {
|
||||
const char *port_space = sanei_config_skip_whitespace(line + 4);
|
||||
if (escl_device != NULL && port_space != NULL) {
|
||||
count++;
|
||||
DBG (10, "New Escl_Device PORT [%d].", port);
|
||||
if (escl_device != NULL) {
|
||||
DBG (10, "New Escl_Device PORT Affected.");
|
||||
escl_device->port_nb = port;
|
||||
}
|
||||
}
|
||||
if (strncmp(line, "model", 5) == 0) {
|
||||
const char *model_space = sanei_config_skip_whitespace(line + 5);
|
||||
DBG (10, "New Escl_Device MODEL [%s].", (model_space ? model_space : "VIDE"));
|
||||
if (escl_device != NULL && model_space != NULL) {
|
||||
count++;
|
||||
DBG (10, "New Escl_Device MODEL Affected.");
|
||||
escl_device->model_name = strdup(model_space);
|
||||
}
|
||||
}
|
||||
if (strncmp(line, "type", 4) == 0) {
|
||||
const char *type_space = sanei_config_skip_whitespace(line + 4);
|
||||
DBG (10, "New Escl_Device TYPE [%s].", (type_space ? type_space : "VIDE"));
|
||||
if (escl_device != NULL && type_space != NULL) {
|
||||
count++;
|
||||
DBG (10, "New Escl_Device TYPE Affected.");
|
||||
escl_device->type = strdup(type_space);
|
||||
}
|
||||
}
|
||||
if (count == 4)
|
||||
return (escl_add_in_list(escl_device));
|
||||
return (SANE_STATUS_GOOD);
|
||||
status = escl_check_and_add_device(escl_device);
|
||||
if (status == SANE_STATUS_GOOD)
|
||||
escl_device = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -337,19 +416,19 @@ init_options(SANE_String_Const name, escl_sane_t *s)
|
|||
s->opt[i].size = sizeof (SANE_Word);
|
||||
s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||||
}
|
||||
s->x_range.min = 0;
|
||||
s->x_range.max = s->scanner->MaxWidth - s->scanner->MinWidth;
|
||||
s->x_range.quant = 1;
|
||||
s->y_range.min = 0;
|
||||
s->y_range.max = s->scanner->MaxHeight - s->scanner->MinHeight;
|
||||
s->y_range.quant = 1;
|
||||
s->x_range.min = PIXEL_TO_MM(s->scanner->MinWidth, 300.0);
|
||||
s->x_range.max = PIXEL_TO_MM(s->scanner->MaxWidth, 300.0);
|
||||
s->x_range.quant = 0;
|
||||
s->y_range.min = PIXEL_TO_MM(s->scanner->MinHeight, 300.0);
|
||||
s->y_range.max = PIXEL_TO_MM(s->scanner->MaxHeight, 300.0);
|
||||
s->y_range.quant = 0;
|
||||
s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
|
||||
s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
|
||||
s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
|
||||
s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
|
||||
s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
|
||||
|
||||
s->opt[OPT_MODE_GROUP].title = "Scan Mode";
|
||||
s->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE;
|
||||
s->opt[OPT_MODE_GROUP].desc = "";
|
||||
s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
|
||||
s->opt[OPT_MODE_GROUP].cap = 0;
|
||||
|
@ -363,8 +442,16 @@ init_options(SANE_String_Const name, escl_sane_t *s)
|
|||
s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
|
||||
s->opt[OPT_MODE].constraint.string_list = s->scanner->ColorModes;
|
||||
s->val[OPT_MODE].s = (char *)strdup(s->scanner->ColorModes[0]);
|
||||
if (!s->val[OPT_MODE].s) {
|
||||
DBG (10, "Color Mode Default allocation failure.\n");
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
s->opt[OPT_MODE].size = max_string_size(s->scanner->ColorModes);
|
||||
s->scanner->default_color = (char *)strdup(s->scanner->ColorModes[0]);
|
||||
if (!s->scanner->default_color) {
|
||||
DBG (10, "Color Mode Default allocation failure.\n");
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
|
||||
s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
|
||||
s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
|
||||
|
@ -389,8 +476,8 @@ init_options(SANE_String_Const name, escl_sane_t *s)
|
|||
s->opt[OPT_GRAY_PREVIEW].type = SANE_TYPE_BOOL;
|
||||
s->val[OPT_GRAY_PREVIEW].w = SANE_FALSE;
|
||||
|
||||
s->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
|
||||
s->opt[OPT_GEOMETRY_GROUP].desc = "";
|
||||
s->opt[OPT_GEOMETRY_GROUP].title = SANE_TITLE_GEOMETRY;
|
||||
s->opt[OPT_GEOMETRY_GROUP].desc = SANE_DESC_GEOMETRY;
|
||||
s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
|
||||
s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
|
||||
s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
|
||||
|
@ -399,37 +486,45 @@ init_options(SANE_String_Const name, escl_sane_t *s)
|
|||
s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
|
||||
s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
|
||||
s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
|
||||
s->opt[OPT_TL_X].unit = SANE_UNIT_PIXEL;
|
||||
s->opt[OPT_TL_X].size = sizeof(SANE_Fixed);
|
||||
s->opt[OPT_TL_X].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||||
s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
|
||||
s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
s->opt[OPT_TL_X].constraint.range = &s->x_range;
|
||||
s->val[OPT_TL_X].w = s->scanner->RiskyLeftMargin;
|
||||
s->val[OPT_TL_X].w = 0;
|
||||
|
||||
s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
|
||||
s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
|
||||
s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
|
||||
s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
|
||||
s->opt[OPT_TL_Y].unit = SANE_UNIT_PIXEL;
|
||||
s->opt[OPT_TL_Y].size = sizeof(SANE_Fixed);
|
||||
s->opt[OPT_TL_Y].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||||
s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
|
||||
s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
s->opt[OPT_TL_Y].constraint.range = &s->y_range;
|
||||
s->val[OPT_TL_Y].w = s->scanner->RiskyTopMargin;
|
||||
s->val[OPT_TL_Y].w = 0;
|
||||
|
||||
s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
|
||||
s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
|
||||
s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
|
||||
s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
|
||||
s->opt[OPT_BR_X].unit = SANE_UNIT_PIXEL;
|
||||
s->opt[OPT_BR_X].size = sizeof(SANE_Fixed);
|
||||
s->opt[OPT_BR_X].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||||
s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
|
||||
s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
s->opt[OPT_BR_X].constraint.range = &s->x_range;
|
||||
s->val[OPT_BR_X].w = s->scanner->MaxWidth;
|
||||
s->val[OPT_BR_X].w = s->x_range.max;
|
||||
|
||||
s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
|
||||
s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
|
||||
s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
|
||||
s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
|
||||
s->opt[OPT_BR_Y].unit = SANE_UNIT_PIXEL;
|
||||
s->opt[OPT_BR_Y].size = sizeof(SANE_Fixed);
|
||||
s->opt[OPT_BR_Y].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||||
s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
|
||||
s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
s->opt[OPT_BR_Y].constraint.range = &s->y_range;
|
||||
s->val[OPT_BR_Y].w = s->scanner->MaxHeight;
|
||||
s->val[OPT_BR_Y].w = s->y_range.max;
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
@ -458,6 +553,10 @@ sane_open(SANE_String_Const name, SANE_Handle *h)
|
|||
if (handler == NULL)
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
handler->name = strdup(name);
|
||||
if (!handler->name) {
|
||||
DBG (10, "Handle Name allocation failure.\n");
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
handler->scanner = escl_capabilities(name, &status);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return (status);
|
||||
|
@ -467,8 +566,8 @@ sane_open(SANE_String_Const name, SANE_Handle *h)
|
|||
handler->ps.depth = 8;
|
||||
handler->ps.last_frame = SANE_TRUE;
|
||||
handler->ps.format = SANE_FRAME_RGB;
|
||||
handler->ps.pixels_per_line = handler->val[OPT_BR_X].w;
|
||||
handler->ps.lines = handler->val[OPT_BR_Y].w;
|
||||
handler->ps.pixels_per_line = MM_TO_PIXEL(handler->val[OPT_BR_X].w, 300.0);
|
||||
handler->ps.lines = MM_TO_PIXEL(handler->val[OPT_BR_Y].w, 300.0);
|
||||
handler->ps.bytes_per_line = handler->ps.pixels_per_line * 3;
|
||||
status = sane_get_parameters(handler, 0);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
|
@ -492,7 +591,11 @@ sane_cancel(SANE_Handle h)
|
|||
{
|
||||
DBG (10, "escl sane_cancel\n");
|
||||
escl_sane_t *handler = h;
|
||||
|
||||
if (handler->scanner->tmp)
|
||||
{
|
||||
fclose(handler->scanner->tmp);
|
||||
handler->scanner->tmp = NULL;
|
||||
}
|
||||
handler->cancel = SANE_TRUE;
|
||||
escl_scanner(handler->name, handler->result);
|
||||
}
|
||||
|
@ -528,7 +631,7 @@ sane_get_option_descriptor(SANE_Handle h, SANE_Int n)
|
|||
|
||||
if ((unsigned) n >= NUM_OPTIONS || n < 0)
|
||||
return (0);
|
||||
return (s->opt + n);
|
||||
return (&s->opt[n]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -556,12 +659,12 @@ sane_control_option(SANE_Handle h, SANE_Int n, SANE_Action a, void *v, SANE_Int
|
|||
return (SANE_STATUS_INVAL);
|
||||
if (a == SANE_ACTION_GET_VALUE) {
|
||||
switch (n) {
|
||||
case OPT_NUM_OPTS:
|
||||
case OPT_RESOLUTION:
|
||||
case OPT_TL_X:
|
||||
case OPT_TL_Y:
|
||||
case OPT_BR_X:
|
||||
case OPT_BR_Y:
|
||||
case OPT_NUM_OPTS:
|
||||
case OPT_RESOLUTION:
|
||||
case OPT_PREVIEW:
|
||||
case OPT_GRAY_PREVIEW:
|
||||
*(SANE_Word *) v = handler->val[n].w;
|
||||
|
@ -581,14 +684,10 @@ sane_control_option(SANE_Handle h, SANE_Int n, SANE_Action a, void *v, SANE_Int
|
|||
case OPT_TL_Y:
|
||||
case OPT_BR_X:
|
||||
case OPT_BR_Y:
|
||||
case OPT_NUM_OPTS:
|
||||
case OPT_RESOLUTION:
|
||||
case OPT_PREVIEW:
|
||||
case OPT_GRAY_PREVIEW:
|
||||
handler->val[n].w = *(SANE_Word *) v;
|
||||
if (i && handler->val[n].w != *(SANE_Word *) v)
|
||||
*i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT;
|
||||
handler->val[n].w = *(SANE_Word *) v;
|
||||
break;
|
||||
case OPT_RESOLUTION:
|
||||
handler->val[n].w = *(SANE_Word *) v;
|
||||
if (i)
|
||||
*i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT;
|
||||
|
@ -597,6 +696,10 @@ sane_control_option(SANE_Handle h, SANE_Int n, SANE_Action a, void *v, SANE_Int
|
|||
if (handler->val[n].s)
|
||||
free (handler->val[n].s);
|
||||
handler->val[n].s = strdup (v);
|
||||
if (!handler->val[n].s) {
|
||||
DBG (10, "OPT_MODE allocation failure.\n");
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
if (i)
|
||||
*i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT;
|
||||
break;
|
||||
|
@ -607,43 +710,6 @@ sane_control_option(SANE_Handle h, SANE_Int n, SANE_Action a, void *v, SANE_Int
|
|||
return (SANE_STATUS_GOOD);
|
||||
}
|
||||
|
||||
#if(defined HAVE_LIBJPEG)
|
||||
static void
|
||||
error_exit(j_common_ptr cinfo)
|
||||
{
|
||||
longjmp(cinfo->client_data, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn static void get_JPEG_dimension(FILE *fp, int *w, int *h)
|
||||
* \brief Function that aims to get the dimensions of the jpeg image wich will be scanned.
|
||||
* This function is called in the "sane_start" function.
|
||||
*/
|
||||
static void
|
||||
get_JPEG_dimension(FILE *fp, int *w, int *h)
|
||||
{
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
struct jpeg_error_mgr jerr;
|
||||
jmp_buf env;
|
||||
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
jerr.error_exit = error_exit;
|
||||
cinfo.client_data = env;
|
||||
if (setjmp(env))
|
||||
return;
|
||||
jpeg_create_decompress(&cinfo);
|
||||
jpeg_stdio_src(&cinfo, fp);
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
cinfo.out_color_space = JCS_RGB;
|
||||
jpeg_start_decompress(&cinfo);
|
||||
*w = cinfo.output_width;
|
||||
*h = cinfo.output_height;
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fseek(fp, SEEK_SET, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \fn SANE_Status sane_start(SANE_Handle h)
|
||||
* \brief Function that initiates aquisition of an image from the device represented by handle 'h'.
|
||||
|
@ -659,6 +725,7 @@ sane_start(SANE_Handle h)
|
|||
escl_sane_t *handler = h;
|
||||
int w = 0;
|
||||
int he = 0;
|
||||
int bps = 0;
|
||||
|
||||
if (handler->name == NULL)
|
||||
return (SANE_STATUS_INVAL);
|
||||
|
@ -666,10 +733,6 @@ sane_start(SANE_Handle h)
|
|||
handler->write_scan_data = SANE_FALSE;
|
||||
handler->decompress_scan_data = SANE_FALSE;
|
||||
handler->end_read = SANE_FALSE;
|
||||
handler->scanner->height = handler->val[OPT_BR_Y].w;
|
||||
handler->scanner->width = handler->val[OPT_BR_X].w;
|
||||
handler->scanner->pos_x = handler->val[OPT_TL_X].w;
|
||||
handler->scanner->pos_y = handler->val[OPT_TL_Y].w;
|
||||
if(handler->scanner->default_color)
|
||||
free(handler->scanner->default_color);
|
||||
if (handler->val[OPT_PREVIEW].w == SANE_TRUE)
|
||||
|
@ -680,6 +743,10 @@ sane_start(SANE_Handle h)
|
|||
handler->scanner->default_color = strdup("Grayscale8");
|
||||
else
|
||||
handler->scanner->default_color = strdup("RGB24");
|
||||
if (!handler->scanner->default_color) {
|
||||
DBG (10, "Default Color allocation failure.\n");
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
for (i = 1; i < handler->scanner->SupportedResolutionsSize; i++)
|
||||
{
|
||||
if (val > handler->scanner->SupportedResolutions[i])
|
||||
|
@ -695,18 +762,52 @@ sane_start(SANE_Handle h)
|
|||
else
|
||||
handler->scanner->default_color = strdup("RGB24");
|
||||
}
|
||||
handler->scanner->height = MM_TO_PIXEL(handler->val[OPT_BR_Y].w, 300.0);
|
||||
handler->scanner->width = MM_TO_PIXEL(handler->val[OPT_BR_X].w, 300.0);
|
||||
handler->scanner->pos_x = MM_TO_PIXEL(handler->val[OPT_TL_X].w, 300.0);
|
||||
handler->scanner->pos_y = MM_TO_PIXEL(handler->val[OPT_TL_Y].w, 300.0);
|
||||
DBG(10, "Calculate Size Image [%dx%d|%dx%d]\n",
|
||||
handler->scanner->pos_x,
|
||||
handler->scanner->pos_y,
|
||||
handler->scanner->height,
|
||||
handler->scanner->width);
|
||||
if (!handler->scanner->default_color) {
|
||||
DBG (10, "Default Color allocation failure.\n");
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
handler->result = escl_newjob(handler->scanner, handler->name, &status);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return (status);
|
||||
status = escl_scan(handler->scanner, handler->name, handler->result);
|
||||
get_JPEG_dimension(handler->scanner->tmp, &w, &he);
|
||||
fseek(handler->scanner->tmp, SEEK_SET, 0);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return (status);
|
||||
if (!strcmp(handler->scanner->default_format, "image/jpeg"))
|
||||
{
|
||||
status = get_JPEG_data(handler->scanner, &w, &he, &bps);
|
||||
}
|
||||
else if (!strcmp(handler->scanner->default_format, "image/png"))
|
||||
{
|
||||
status = get_PNG_data(handler->scanner, &w, &he, &bps);
|
||||
}
|
||||
else if (!strcmp(handler->scanner->default_format, "image/tiff"))
|
||||
{
|
||||
status = get_TIFF_data(handler->scanner, &w, &he, &bps);
|
||||
}
|
||||
else {
|
||||
DBG(10, "Unknow image format\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
DBG(10, "2-Size Image [%dx%d|%dx%d]\n", 0, 0, w, he);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return (status);
|
||||
handler->ps.depth = 8;
|
||||
handler->ps.pixels_per_line = w;
|
||||
handler->ps.lines = he;
|
||||
handler->ps.bytes_per_line = w * 3;
|
||||
handler->ps.bytes_per_line = w * bps;
|
||||
handler->ps.last_frame = SANE_TRUE;
|
||||
handler->ps.format = SANE_FRAME_RGB;
|
||||
DBG(10, "Real Size Image [%dx%d|%dx%d]\n", 0, 0, w, he);
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
@ -733,162 +834,11 @@ sane_get_parameters(SANE_Handle h, SANE_Parameters *p)
|
|||
p->format = SANE_FRAME_RGB;
|
||||
p->pixels_per_line = handler->ps.pixels_per_line;
|
||||
p->lines = handler->ps.lines;
|
||||
p->bytes_per_line = handler->ps.pixels_per_line * 3;
|
||||
p->bytes_per_line = handler->ps.bytes_per_line;
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
#if(defined HAVE_LIBJPEG)
|
||||
/**
|
||||
* \fn static boolean fill_input_buffer(j_decompress_ptr cinfo)
|
||||
* \brief Called in the "skip_input_data" function.
|
||||
*
|
||||
* \return TRUE (everything is OK)
|
||||
*/
|
||||
static boolean
|
||||
fill_input_buffer(j_decompress_ptr cinfo)
|
||||
{
|
||||
my_source_mgr *src = (my_source_mgr *) cinfo->src;
|
||||
int nbytes = 0;
|
||||
|
||||
nbytes = fread(src->buffer, 1, INPUT_BUFFER_SIZE, src->ctx);
|
||||
if (nbytes <= 0) {
|
||||
src->buffer[0] = (unsigned char) 0xFF;
|
||||
src->buffer[1] = (unsigned char) JPEG_EOI;
|
||||
nbytes = 2;
|
||||
}
|
||||
src->pub.next_input_byte = src->buffer;
|
||||
src->pub.bytes_in_buffer = nbytes;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn static void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
|
||||
* \brief Called in the "jpeg_RW_src" function.
|
||||
*/
|
||||
static void
|
||||
skip_input_data(j_decompress_ptr cinfo, long num_bytes)
|
||||
{
|
||||
my_source_mgr *src = (my_source_mgr *) cinfo->src;
|
||||
|
||||
if (num_bytes > 0) {
|
||||
while (num_bytes > (long) src->pub.bytes_in_buffer) {
|
||||
num_bytes -= (long) src->pub.bytes_in_buffer;
|
||||
(void) src->pub.fill_input_buffer(cinfo);
|
||||
}
|
||||
src->pub.next_input_byte += (size_t) num_bytes;
|
||||
src->pub.bytes_in_buffer -= (size_t) num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
term_source(j_decompress_ptr __sane_unused__ cinfo)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
init_source(j_decompress_ptr __sane_unused__ cinfo)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn static void jpeg_RW_src(j_decompress_ptr cinfo, FILE *ctx)
|
||||
* \brief Called in the "escl_sane_decompressor" function.
|
||||
*/
|
||||
static void
|
||||
jpeg_RW_src(j_decompress_ptr cinfo, FILE *ctx)
|
||||
{
|
||||
my_source_mgr *src;
|
||||
|
||||
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;
|
||||
src->pub.fill_input_buffer = fill_input_buffer;
|
||||
src->pub.skip_input_data = skip_input_data;
|
||||
src->pub.resync_to_restart = jpeg_resync_to_restart;
|
||||
src->pub.term_source = term_source;
|
||||
src->ctx = ctx;
|
||||
src->pub.bytes_in_buffer = 0;
|
||||
src->pub.next_input_byte = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
my_error_exit(j_common_ptr cinfo)
|
||||
{
|
||||
struct my_error_mgr *err = (struct my_error_mgr *)cinfo->err;
|
||||
|
||||
longjmp(err->escape, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
output_no_message(j_common_ptr __sane_unused__ cinfo)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn SANE_Status escl_sane_decompressor(escl_sane_t *handler)
|
||||
* \brief Function that aims to decompress the jpeg image to SANE be able to read the image.
|
||||
* This function is called in the "sane_read" function.
|
||||
*
|
||||
* \return SANE_STATUS_GOOD (if everything is OK, otherwise, SANE_STATUS_NO_MEM/SANE_STATUS_INVAL)
|
||||
*/
|
||||
SANE_Status
|
||||
escl_sane_decompressor(escl_sane_t *handler)
|
||||
{
|
||||
int start = 0;
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
JSAMPROW rowptr[1];
|
||||
unsigned char *surface = NULL;
|
||||
struct my_error_mgr jerr;
|
||||
int lineSize = 0;
|
||||
|
||||
if (handler->scanner->tmp == NULL)
|
||||
return (SANE_STATUS_INVAL);
|
||||
fseek(handler->scanner->tmp, SEEK_SET, 0);
|
||||
start = ftell(handler->scanner->tmp);
|
||||
cinfo.err = jpeg_std_error(&jerr.errmgr);
|
||||
jerr.errmgr.error_exit = my_error_exit;
|
||||
jerr.errmgr.output_message = output_no_message;
|
||||
if (setjmp(jerr.escape)) {
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
if (surface != NULL)
|
||||
free(surface);
|
||||
return (SANE_STATUS_INVAL);
|
||||
}
|
||||
jpeg_create_decompress(&cinfo);
|
||||
jpeg_RW_src(&cinfo, handler->scanner->tmp);
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
cinfo.out_color_space = JCS_RGB;
|
||||
cinfo.quantize_colors = FALSE;
|
||||
jpeg_calc_output_dimensions(&cinfo);
|
||||
surface = malloc(cinfo.output_width * cinfo.output_height * cinfo.output_components);
|
||||
if (surface == NULL) {
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fseek(handler->scanner->tmp, start, SEEK_SET);
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
lineSize = cinfo.output_width * cinfo.output_components;
|
||||
jpeg_start_decompress(&cinfo);
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
rowptr[0] = (JSAMPROW)surface + (lineSize * cinfo.output_scanline);
|
||||
jpeg_read_scanlines(&cinfo, rowptr, (JDIMENSION) 1);
|
||||
}
|
||||
handler->img_data = surface;
|
||||
handler->img_size = lineSize * cinfo.output_height;
|
||||
handler->img_read = 0;
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(handler->scanner->tmp);
|
||||
handler->scanner->tmp = NULL;
|
||||
return (SANE_STATUS_GOOD);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \fn SANE_Status sane_read(SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *len)
|
||||
|
@ -914,34 +864,31 @@ sane_read(SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *len)
|
|||
if (!handler->write_scan_data)
|
||||
handler->write_scan_data = SANE_TRUE;
|
||||
if (!handler->decompress_scan_data) {
|
||||
if (handler->scanner->tmp == NULL)
|
||||
return (SANE_STATUS_INVAL);
|
||||
status = escl_sane_decompressor(handler);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
return (status);
|
||||
handler->decompress_scan_data = SANE_TRUE;
|
||||
}
|
||||
if (handler->img_data == NULL)
|
||||
if (handler->scanner->img_data == NULL)
|
||||
return (SANE_STATUS_INVAL);
|
||||
if (!handler->end_read) {
|
||||
readbyte = min((handler->img_size - handler->img_read), maxlen);
|
||||
memcpy(buf, handler->img_data + handler->img_read, readbyte);
|
||||
handler->img_read = handler->img_read + readbyte;
|
||||
readbyte = min((handler->scanner->img_size - handler->scanner->img_read), maxlen);
|
||||
memcpy(buf, handler->scanner->img_data + handler->scanner->img_read, readbyte);
|
||||
handler->scanner->img_read = handler->scanner->img_read + readbyte;
|
||||
*len = readbyte;
|
||||
if (handler->img_read == handler->img_size)
|
||||
if (handler->scanner->img_read == handler->scanner->img_size)
|
||||
handler->end_read = SANE_TRUE;
|
||||
else if (handler->img_read > handler->img_size) {
|
||||
else if (handler->scanner->img_read > handler->scanner->img_size) {
|
||||
*len = 0;
|
||||
handler->end_read = SANE_TRUE;
|
||||
free(handler->img_data);
|
||||
handler->img_data = NULL;
|
||||
free(handler->scanner->img_data);
|
||||
handler->scanner->img_data = NULL;
|
||||
return (SANE_STATUS_INVAL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
*len = 0;
|
||||
free(handler->img_data);
|
||||
handler->img_data = NULL;
|
||||
free(handler->scanner->img_data);
|
||||
handler->scanner->img_data = NULL;
|
||||
return (SANE_STATUS_EOF);
|
||||
}
|
||||
return (SANE_STATUS_GOOD);
|
||||
|
|
|
@ -43,11 +43,25 @@
|
|||
#include "../include/sane/sane.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef BACKEND_NAME
|
||||
#define BACKEND_NAME escl
|
||||
#endif
|
||||
|
||||
#define DEBUG_NOT_STATIC
|
||||
#include "../include/sane/sanei_debug.h"
|
||||
|
||||
#ifndef DBG_LEVEL
|
||||
#define DBG_LEVEL PASTE(sanei_debug_, BACKEND_NAME)
|
||||
#endif
|
||||
#ifndef NDEBUG
|
||||
# define DBGDUMP(level, buf, size) \
|
||||
do { if (DBG_LEVEL >= (level)) sanei_escl_dbgdump(buf, size); } while (0)
|
||||
#else
|
||||
# define DBGDUMP(level, buf, size)
|
||||
#endif
|
||||
|
||||
#define ESCL_CONFIG_FILE "escl.conf"
|
||||
|
||||
typedef struct {
|
||||
|
@ -78,7 +92,7 @@ typedef struct capabilities
|
|||
int pos_x;
|
||||
int pos_y;
|
||||
SANE_String default_color;
|
||||
SANE_String_Const default_format;
|
||||
SANE_String default_format;
|
||||
SANE_Int default_resolution;
|
||||
int MinWidth;
|
||||
int MaxWidth;
|
||||
|
@ -102,6 +116,9 @@ typedef struct capabilities
|
|||
int RiskyTopMargin;
|
||||
int RiskyBottomMargin;
|
||||
FILE *tmp;
|
||||
unsigned char *img_data;
|
||||
long img_size;
|
||||
long img_read;
|
||||
int format_ext;
|
||||
} capabilities_t;
|
||||
|
||||
|
@ -135,12 +152,30 @@ enum
|
|||
NUM_OPTIONS
|
||||
};
|
||||
|
||||
#define PIXEL_TO_MM(pixels, dpi) SANE_FIX((double)pixels * 25.4 / (dpi))
|
||||
#define MM_TO_PIXEL(millimeters, dpi) (SANE_Word)round(SANE_UNFIX(millimeters) * (dpi) / 25.4)
|
||||
|
||||
ESCL_Device *escl_devices(SANE_Status *status);
|
||||
SANE_Status escl_device_add(int port_nb, const char *model_name, char *ip_address, char *type);
|
||||
SANE_Status escl_device_add(int port_nb, const char *model_name,
|
||||
char *ip_address, char *type);
|
||||
SANE_Status escl_status(SANE_String_Const name);
|
||||
capabilities_t *escl_capabilities(SANE_String_Const name, SANE_Status *status);
|
||||
char *escl_newjob(capabilities_t *scanner, SANE_String_Const name, SANE_Status *status);
|
||||
SANE_Status escl_scan(capabilities_t *scanner, SANE_String_Const name, char *result);
|
||||
char *escl_newjob(capabilities_t *scanner, SANE_String_Const name,
|
||||
SANE_Status *status);
|
||||
SANE_Status escl_scan(capabilities_t *scanner, SANE_String_Const name,
|
||||
char *result);
|
||||
void escl_scanner(SANE_String_Const name, char *result);
|
||||
|
||||
unsigned char *escl_crop_surface(capabilities_t *scanner, unsigned char *surface,
|
||||
int w, int h, int bps, int *width, int *height);
|
||||
|
||||
// JPEG
|
||||
SANE_Status get_JPEG_data(capabilities_t *scanner, int *width, int *height, int *bps);
|
||||
|
||||
// PNG
|
||||
SANE_Status get_PNG_data(capabilities_t *scanner, int *width, int *height, int *bps);
|
||||
|
||||
// TIFF
|
||||
SANE_Status get_TIFF_data(capabilities_t *scanner, int *width, int *height, int *bps);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
This file implements a SANE backend for eSCL scanners. */
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#include "escl.h"
|
||||
|
||||
|
@ -181,7 +183,34 @@ find_valor_of_array_variables(xmlNode *node, capabilities_t *scanner)
|
|||
else if (strcmp(name, "ContentType") == 0)
|
||||
scanner->ContentTypes = char_to_array(scanner->ContentTypes, &scanner->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++)
|
||||
{
|
||||
if (scanner->default_format == NULL && !strcmp(scanner->DocumentFormats[i], "image/jpeg"))
|
||||
{
|
||||
scanner->default_format = strdup("image/jpeg");
|
||||
}
|
||||
#if(defined HAVE_LIBPNG)
|
||||
else if(!strcmp(scanner->DocumentFormats[i], "image/png") && (scanner->default_format == NULL || strcmp(scanner->default_format, "image/tiff")))
|
||||
{
|
||||
if (scanner->default_format)
|
||||
free(scanner->default_format);
|
||||
scanner->default_format = strdup("image/png");
|
||||
}
|
||||
#endif
|
||||
#if(defined HAVE_TIFFIO_H)
|
||||
else if(!strcmp(scanner->DocumentFormats[i], "image/tiff"))
|
||||
{
|
||||
if (scanner->default_format)
|
||||
free(scanner->default_format);
|
||||
scanner->default_format = strdup("image/tiff");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
fprintf(stderr, "Capability : [%s]\n", scanner->default_format);
|
||||
}
|
||||
else if (strcmp(name, "DocumentFormatExt") == 0)
|
||||
scanner->format_ext = 1;
|
||||
else if (strcmp(name, "Intent") == 0)
|
||||
|
@ -316,19 +345,20 @@ escl_capabilities(SANE_String_Const name, SANE_Status *status)
|
|||
*status = SANE_STATUS_NO_MEM;
|
||||
var->memory = malloc(1);
|
||||
var->size = 0;
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
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);
|
||||
}
|
||||
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) {
|
||||
fprintf(stderr, "THERE IS NO SCANNER\n");
|
||||
DBG( 1, "The scanner didn't respond.\n");
|
||||
*status = SANE_STATUS_INVAL;
|
||||
}
|
||||
data = xmlReadMemory(var->memory, var->size, "file.xml", NULL, 0);
|
||||
|
@ -343,6 +373,5 @@ escl_capabilities(SANE_String_Const name, SANE_Status *status)
|
|||
xmlMemoryDump();
|
||||
curl_easy_cleanup(curl_handle);
|
||||
free(var->memory);
|
||||
curl_global_cleanup();
|
||||
return (scanner);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2020 Thierry HUCHARD <thierry@ordissimo.com>
|
||||
|
||||
This file is part of the SANE package.
|
||||
|
||||
SANE is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
SANE is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with sane; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
This file implements a SANE backend for eSCL scanners. */
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#include "escl.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
unsigned char *
|
||||
escl_crop_surface(capabilities_t *scanner,
|
||||
unsigned char *surface,
|
||||
int w,
|
||||
int h,
|
||||
int bps,
|
||||
int *width,
|
||||
int *height)
|
||||
{
|
||||
int x_off = 0, x = 0;
|
||||
int real_w = 0;
|
||||
int y_off = 0, y = 0;
|
||||
int real_h = 0;
|
||||
unsigned char *surface_crop = NULL;
|
||||
|
||||
DBG( 1, "Escl Image Crop\n");
|
||||
if (w < (int)scanner->width)
|
||||
scanner->width = w;
|
||||
if (scanner->pos_x < 0)
|
||||
scanner->pos_x = 0;
|
||||
|
||||
if (h < (int)scanner->height)
|
||||
scanner->height = h;
|
||||
if (scanner->pos_x < 0)
|
||||
scanner->pos_x = 0;
|
||||
|
||||
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) {
|
||||
surface_crop = (unsigned char *)malloc (sizeof (unsigned char) * real_w
|
||||
* real_h * bps);
|
||||
if(!surface_crop) {
|
||||
DBG( 1, "Escl Crop : Surface_crop Memory allocation problem\n");
|
||||
free(surface);
|
||||
surface = NULL;
|
||||
goto finish;
|
||||
}
|
||||
for (y = 0; y < real_h; y++)
|
||||
{
|
||||
for (x = 0; x < real_w; x++)
|
||||
{
|
||||
surface_crop[y * real_w + x] = surface[(y + y_off) * w + x + x_off];
|
||||
}
|
||||
}
|
||||
free(surface);
|
||||
surface = surface_crop;
|
||||
}
|
||||
// we don't need row pointers anymore
|
||||
scanner->img_data = surface;
|
||||
scanner->img_size = (int)(real_w * real_h * bps);
|
||||
scanner->img_read = 0;
|
||||
finish:
|
||||
return surface;
|
||||
}
|
|
@ -21,6 +21,9 @@
|
|||
|
||||
This file implements a SANE backend for eSCL scanners. */
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#include "escl.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -142,21 +145,21 @@ escl_devices(SANE_Status *status)
|
|||
|
||||
*status = SANE_STATUS_GOOD;
|
||||
if (!(simple_poll = avahi_simple_poll_new())) {
|
||||
fprintf(stderr, "Failed to create simple poll object.\n");
|
||||
DBG( 1, "Failed to create simple poll object.\n");
|
||||
*status = SANE_STATUS_INVAL;
|
||||
goto fail;
|
||||
}
|
||||
client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0,
|
||||
client_callback, NULL, &error);
|
||||
if (!client) {
|
||||
fprintf(stderr, "Failed to create client: %s\n", avahi_strerror(error));
|
||||
DBG( 1, "Failed to create client: %s\n", avahi_strerror(error));
|
||||
*status = SANE_STATUS_INVAL;
|
||||
goto fail;
|
||||
}
|
||||
if (!(sb = avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
|
||||
AVAHI_PROTO_UNSPEC, "_uscan._tcp",
|
||||
NULL, 0, browse_callback, client))) {
|
||||
fprintf(stderr, "Failed to create service browser: %s\n",
|
||||
DBG( 1, "Failed to create service browser: %s\n",
|
||||
avahi_strerror(avahi_client_errno(client)));
|
||||
*status = SANE_STATUS_INVAL;
|
||||
goto fail;
|
||||
|
@ -165,7 +168,7 @@ escl_devices(SANE_Status *status)
|
|||
AVAHI_PROTO_UNSPEC,
|
||||
"_uscans._tcp", NULL, 0,
|
||||
browse_callback, client))) {
|
||||
fprintf(stderr, "Failed to create service browser: %s\n",
|
||||
DBG( 1, "Failed to create service browser: %s\n",
|
||||
avahi_strerror(avahi_client_errno(client)));
|
||||
*status = SANE_STATUS_INVAL;
|
||||
goto fail;
|
||||
|
|
|
@ -0,0 +1,255 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2019 Touboul Nathane
|
||||
Copyright (C) 2019 Thierry HUCHARD <thierry@ordissimo.com>
|
||||
|
||||
This file is part of the SANE package.
|
||||
|
||||
SANE is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
SANE is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with sane; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
This file implements a SANE backend for eSCL scanners. */
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#include "escl.h"
|
||||
|
||||
#include "../include/sane/sanei.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if(defined HAVE_LIBJPEG)
|
||||
# include <jpeglib.h>
|
||||
#endif
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
#define INPUT_BUFFER_SIZE 4096
|
||||
|
||||
#if(defined HAVE_LIBJPEG)
|
||||
struct my_error_mgr
|
||||
{
|
||||
struct jpeg_error_mgr errmgr;
|
||||
jmp_buf escape;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct jpeg_source_mgr pub;
|
||||
FILE *ctx;
|
||||
unsigned char buffer[INPUT_BUFFER_SIZE];
|
||||
} my_source_mgr;
|
||||
|
||||
/**
|
||||
* \fn static boolean fill_input_buffer(j_decompress_ptr cinfo)
|
||||
* \brief Called in the "skip_input_data" function.
|
||||
*
|
||||
* \return TRUE (everything is OK)
|
||||
*/
|
||||
static boolean
|
||||
fill_input_buffer(j_decompress_ptr cinfo)
|
||||
{
|
||||
my_source_mgr *src = (my_source_mgr *) cinfo->src;
|
||||
int nbytes = 0;
|
||||
|
||||
nbytes = fread(src->buffer, 1, INPUT_BUFFER_SIZE, src->ctx);
|
||||
if (nbytes <= 0) {
|
||||
src->buffer[0] = (unsigned char) 0xFF;
|
||||
src->buffer[1] = (unsigned char) JPEG_EOI;
|
||||
nbytes = 2;
|
||||
}
|
||||
src->pub.next_input_byte = src->buffer;
|
||||
src->pub.bytes_in_buffer = nbytes;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn static void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
|
||||
* \brief Called in the "jpeg_RW_src" function.
|
||||
*/
|
||||
static void
|
||||
skip_input_data(j_decompress_ptr cinfo, long num_bytes)
|
||||
{
|
||||
my_source_mgr *src = (my_source_mgr *) cinfo->src;
|
||||
|
||||
if (num_bytes > 0) {
|
||||
while (num_bytes > (long) src->pub.bytes_in_buffer) {
|
||||
num_bytes -= (long) src->pub.bytes_in_buffer;
|
||||
(void) src->pub.fill_input_buffer(cinfo);
|
||||
}
|
||||
src->pub.next_input_byte += (size_t) num_bytes;
|
||||
src->pub.bytes_in_buffer -= (size_t) num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
term_source(j_decompress_ptr __sane_unused__ cinfo)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
init_source(j_decompress_ptr __sane_unused__ cinfo)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn static void jpeg_RW_src(j_decompress_ptr cinfo, FILE *ctx)
|
||||
* \brief Called in the "escl_sane_decompressor" function.
|
||||
*/
|
||||
static void
|
||||
jpeg_RW_src(j_decompress_ptr cinfo, FILE *ctx)
|
||||
{
|
||||
my_source_mgr *src;
|
||||
|
||||
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;
|
||||
src->pub.fill_input_buffer = fill_input_buffer;
|
||||
src->pub.skip_input_data = skip_input_data;
|
||||
src->pub.resync_to_restart = jpeg_resync_to_restart;
|
||||
src->pub.term_source = term_source;
|
||||
src->ctx = ctx;
|
||||
src->pub.bytes_in_buffer = 0;
|
||||
src->pub.next_input_byte = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
my_error_exit(j_common_ptr cinfo)
|
||||
{
|
||||
struct my_error_mgr *err = (struct my_error_mgr *)cinfo->err;
|
||||
|
||||
longjmp(err->escape, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
output_no_message(j_common_ptr __sane_unused__ cinfo)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn SANE_Status escl_sane_decompressor(escl_sane_t *handler)
|
||||
* \brief Function that aims to decompress the jpeg image to SANE be able to read the image.
|
||||
* This function is called in the "sane_read" function.
|
||||
*
|
||||
* \return SANE_STATUS_GOOD (if everything is OK, otherwise, SANE_STATUS_NO_MEM/SANE_STATUS_INVAL)
|
||||
*/
|
||||
SANE_Status
|
||||
get_JPEG_data(capabilities_t *scanner, int *width, int *height, int *bps)
|
||||
{
|
||||
int start = 0;
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
JSAMPROW rowptr[1];
|
||||
unsigned char *surface = NULL;
|
||||
struct my_error_mgr jerr;
|
||||
int lineSize = 0;
|
||||
JDIMENSION x_off = 0;
|
||||
JDIMENSION y_off = 0;
|
||||
JDIMENSION w = 0;
|
||||
JDIMENSION h = 0;
|
||||
int pos = 0;
|
||||
|
||||
if (scanner->tmp == NULL)
|
||||
return (SANE_STATUS_INVAL);
|
||||
fseek(scanner->tmp, SEEK_SET, 0);
|
||||
start = ftell(scanner->tmp);
|
||||
cinfo.err = jpeg_std_error(&jerr.errmgr);
|
||||
jerr.errmgr.error_exit = my_error_exit;
|
||||
jerr.errmgr.output_message = output_no_message;
|
||||
if (setjmp(jerr.escape)) {
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
if (surface != NULL)
|
||||
free(surface);
|
||||
fseek(scanner->tmp, start, SEEK_SET);
|
||||
DBG( 1, "Escl Jpeg : Error reading jpeg\n");
|
||||
if (scanner->tmp) {
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
}
|
||||
return (SANE_STATUS_INVAL);
|
||||
}
|
||||
jpeg_create_decompress(&cinfo);
|
||||
jpeg_RW_src(&cinfo, scanner->tmp);
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
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_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;
|
||||
surface = malloc(w * h * cinfo.output_components);
|
||||
if (surface == NULL) {
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
DBG( 1, "Escl Jpeg : Memory allocation problem\n");
|
||||
if (scanner->tmp) {
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
}
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
}
|
||||
jpeg_start_decompress(&cinfo);
|
||||
if (x_off > 0 || w < cinfo.output_width)
|
||||
jpeg_crop_scanline(&cinfo, &x_off, &w);
|
||||
lineSize = w * cinfo.output_components;
|
||||
if (y_off > 0)
|
||||
jpeg_skip_scanlines(&cinfo, y_off);
|
||||
pos = 0;
|
||||
while (cinfo.output_scanline < (unsigned int)scanner->height) {
|
||||
rowptr[0] = (JSAMPROW)surface + (lineSize * pos); // ..cinfo.output_scanline);
|
||||
jpeg_read_scanlines(&cinfo, rowptr, (JDIMENSION) 1);
|
||||
pos++;
|
||||
}
|
||||
scanner->img_data = surface;
|
||||
scanner->img_size = lineSize * h;
|
||||
scanner->img_read = 0;
|
||||
*width = w;
|
||||
*height = h;
|
||||
*bps = cinfo.output_components;
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
return (SANE_STATUS_GOOD);
|
||||
}
|
||||
#else
|
||||
|
||||
SANE_Status
|
||||
get_JPEG_data(capabilities_t __sane_unused__ *scanner,
|
||||
int __sane_unused__ *width,
|
||||
int __sane_unused__ *height,
|
||||
int __sane_unused__ *bps)
|
||||
{
|
||||
return (SANE_STATUS_INVAL);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -21,6 +21,9 @@
|
|||
|
||||
This file implements a SANE backend for eSCL scanners. */
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#include "escl.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -29,6 +32,12 @@
|
|||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#ifdef PATH_MAX
|
||||
# undef PATH_MAX
|
||||
#endif
|
||||
|
||||
#define PATH_MAX 4096
|
||||
|
||||
struct uploading
|
||||
{
|
||||
const char *read_data;
|
||||
|
@ -54,7 +63,7 @@ static const char settings[] =
|
|||
" <pwg:YOffset>%d</pwg:YOffset>" \
|
||||
" </pwg:ScanRegion>" \
|
||||
" </pwg:ScanRegions>" \
|
||||
" <pwg:DocumentFormat>image/jpeg</pwg:DocumentFormat>" \
|
||||
" <pwg:DocumentFormat>%s</pwg:DocumentFormat>" \
|
||||
"%s" \
|
||||
" <scan:ColorMode>%s</scan:ColorMode>" \
|
||||
" <scan:XResolution>%d</scan:XResolution>" \
|
||||
|
@ -62,9 +71,15 @@ static const char settings[] =
|
|||
" <pwg:InputSource>Platen</pwg:InputSource>" \
|
||||
"</scan:ScanSettings>";
|
||||
|
||||
static const char formatExt[] =
|
||||
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 :
|
||||
|
@ -96,7 +111,7 @@ download_callback(void *str, size_t size, size_t nmemb, void *userp)
|
|||
char *content = realloc(download->memory, download->size + realsize + 1);
|
||||
|
||||
if (content == NULL) {
|
||||
fprintf(stderr, "not enough memory (realloc returned NULL)\n");
|
||||
DBG( 1, "Not enough memory (realloc returned NULL)\n");
|
||||
return (0);
|
||||
}
|
||||
download->memory = content;
|
||||
|
@ -127,30 +142,48 @@ escl_newjob (capabilities_t *scanner, SANE_String_Const name, SANE_Status *statu
|
|||
char *location = NULL;
|
||||
char *result = NULL;
|
||||
char *temporary = NULL;
|
||||
char *f_ext = "";
|
||||
char *format_ext = NULL;
|
||||
|
||||
*status = SANE_STATUS_GOOD;
|
||||
if (name == NULL || scanner == NULL) {
|
||||
*status = SANE_STATUS_NO_MEM;
|
||||
DBG( 1, "Create NewJob : the name or the scan are invalid.\n");
|
||||
return (NULL);
|
||||
}
|
||||
upload = (struct uploading *)calloc(1, sizeof(struct uploading));
|
||||
if (upload == NULL) {
|
||||
*status = SANE_STATUS_NO_MEM;
|
||||
DBG( 1, "Create NewJob : memory allocation failure\n");
|
||||
return (NULL);
|
||||
}
|
||||
download = (struct downloading *)calloc(1, sizeof(struct downloading));
|
||||
if (download == NULL) {
|
||||
free(upload);
|
||||
DBG( 1, "Create NewJob : memory allocation failure\n");
|
||||
*status = SANE_STATUS_NO_MEM;
|
||||
return (NULL);
|
||||
}
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
curl_handle = curl_easy_init();
|
||||
if (scanner->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;
|
||||
}
|
||||
else
|
||||
format_ext = f_ext;
|
||||
DBG( 1, "Create NewJob : %s\n", scanner->default_format);
|
||||
if (curl_handle != NULL) {
|
||||
snprintf(cap_data, sizeof(cap_data), settings, scanner->height, scanner->width, 0, 0,
|
||||
(scanner->format_ext == 1 ? formatExt : ""),
|
||||
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);
|
||||
//fprintf(stderr, "CAP_DATA = %s\n", cap_data);
|
||||
DBG( 1, "Create NewJob : %s\n", cap_data);
|
||||
upload->read_data = strdup(cap_data);
|
||||
upload->size = strlen(cap_data);
|
||||
download->memory = malloc(1);
|
||||
|
@ -168,37 +201,44 @@ escl_newjob (capabilities_t *scanner, SANE_String_Const name, SANE_Status *statu
|
|||
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) {
|
||||
fprintf(stderr, "THERE IS NO SCANNER\n");
|
||||
DBG( 1, "Create NewJob : the scanner responded incorrectly.\n");
|
||||
*status = SANE_STATUS_INVAL;
|
||||
}
|
||||
else {
|
||||
if (download->memory != NULL) {
|
||||
if (strstr(download->memory, "Location:")) {
|
||||
temporary = strrchr(download->memory, '/');
|
||||
char *tmp_location = strstr(download->memory, "Location:");
|
||||
if (tmp_location) {
|
||||
temporary = strchr(tmp_location, '\r');
|
||||
if (temporary == NULL)
|
||||
temporary = strchr(tmp_location, '\n');
|
||||
if (temporary != NULL) {
|
||||
location = strchr(temporary, '\r');
|
||||
if (location == NULL)
|
||||
location = strchr(temporary, '\n');
|
||||
else {
|
||||
*location = '\0';
|
||||
result = strdup(temporary);
|
||||
}
|
||||
*temporary = '\0';
|
||||
location = strrchr(tmp_location,'/');
|
||||
if (location) {
|
||||
result = strdup(location);
|
||||
DBG( 1, "Create NewJob : %s\n", result);
|
||||
*temporary = '\n';
|
||||
}
|
||||
}
|
||||
if (result == NULL) {
|
||||
DBG( 1, "Error : Create NewJob, no location\n");
|
||||
*status = SANE_STATUS_INVAL;
|
||||
}
|
||||
free(download->memory);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "THERE IS NO LOCATION\n");
|
||||
DBG( 1, "Create NewJob : The creation of the failed job\n");
|
||||
*status = SANE_STATUS_INVAL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*status = SANE_STATUS_NO_MEM;
|
||||
DBG( 1, "Create NewJob : The creation of the failed job\n");
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
curl_easy_cleanup(curl_handle);
|
||||
}
|
||||
curl_global_cleanup();
|
||||
if (upload != NULL)
|
||||
free(upload);
|
||||
if (download != NULL)
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2019 Touboul Nathane
|
||||
Copyright (C) 2019 Thierry HUCHARD <thierry@ordissimo.com>
|
||||
|
||||
This file is part of the SANE package.
|
||||
|
||||
SANE is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
SANE is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with sane; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
This file implements a SANE backend for eSCL scanners. */
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#include "escl.h"
|
||||
|
||||
#include "../include/sane/sanei.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if(defined HAVE_LIBPNG)
|
||||
#include <png.h>
|
||||
#endif
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
|
||||
#if(defined HAVE_LIBPNG)
|
||||
|
||||
/**
|
||||
* \fn SANE_Status escl_sane_decompressor(escl_sane_t *handler)
|
||||
* \brief Function that aims to decompress the png image to SANE be able to read the image.
|
||||
* This function is called in the "sane_read" function.
|
||||
*
|
||||
* \return SANE_STATUS_GOOD (if everything is OK, otherwise, SANE_STATUS_NO_MEM/SANE_STATUS_INVAL)
|
||||
*/
|
||||
SANE_Status
|
||||
get_PNG_data(capabilities_t *scanner, int *width, int *height, int *bps)
|
||||
{
|
||||
unsigned int w = 0;
|
||||
unsigned int h = 0;
|
||||
int components = 3;
|
||||
unsigned char *surface = NULL; /* Image data */
|
||||
unsigned int i = 0;
|
||||
png_byte magic[8];
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
|
||||
// read magic number
|
||||
fread (magic, 1, sizeof (magic), scanner->tmp);
|
||||
// check for valid magic number
|
||||
if (!png_check_sig (magic, sizeof (magic)))
|
||||
{
|
||||
DBG( 1, "Escl Png : PNG error is not a valid PNG image!\n");
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto close_file;
|
||||
}
|
||||
// create a png read struct
|
||||
png_structp png_ptr = png_create_read_struct
|
||||
(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!png_ptr)
|
||||
{
|
||||
DBG( 1, "Escl Png : PNG error create a png read struct\n");
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto close_file;
|
||||
}
|
||||
// create a png info struct
|
||||
png_infop info_ptr = png_create_info_struct (png_ptr);
|
||||
if (!info_ptr)
|
||||
{
|
||||
DBG( 1, "Escl Png : PNG error create a png info struct\n");
|
||||
png_destroy_read_struct (&png_ptr, NULL, NULL);
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto close_file;
|
||||
}
|
||||
// initialize the setjmp for returning properly after a libpng
|
||||
// error occured
|
||||
if (setjmp (png_jmpbuf (png_ptr)))
|
||||
{
|
||||
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
|
||||
if (surface)
|
||||
free (surface);
|
||||
DBG( 1, "Escl Png : PNG read error.\n");
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto close_file;
|
||||
}
|
||||
// setup libpng for using standard C fread() function
|
||||
// with our FILE pointer
|
||||
png_init_io (png_ptr, scanner->tmp);
|
||||
// tell libpng that we have already read the magic number
|
||||
png_set_sig_bytes (png_ptr, sizeof (magic));
|
||||
|
||||
// read png info
|
||||
png_read_info (png_ptr, info_ptr);
|
||||
|
||||
int bit_depth, color_type;
|
||||
// get some usefull information from header
|
||||
bit_depth = png_get_bit_depth (png_ptr, info_ptr);
|
||||
color_type = png_get_color_type (png_ptr, info_ptr);
|
||||
// convert index color images to RGB images
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_palette_to_rgb (png_ptr);
|
||||
else if (color_type != PNG_COLOR_TYPE_RGB && color_type != PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
{
|
||||
DBG(1, "PNG format not supported.\n");
|
||||
status = SANE_STATUS_NO_MEM;
|
||||
goto close_file;
|
||||
}
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
components = 4;
|
||||
else
|
||||
components = 3;
|
||||
|
||||
if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha (png_ptr);
|
||||
if (bit_depth == 16)
|
||||
png_set_strip_16 (png_ptr);
|
||||
else if (bit_depth < 8)
|
||||
png_set_packing (png_ptr);
|
||||
// update info structure to apply transformations
|
||||
png_read_update_info (png_ptr, info_ptr);
|
||||
// retrieve updated information
|
||||
png_get_IHDR (png_ptr, info_ptr,
|
||||
(png_uint_32*)(&w),
|
||||
(png_uint_32*)(&h),
|
||||
&bit_depth, &color_type,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
*bps = components;
|
||||
// we can now allocate memory for storing pixel data
|
||||
surface = (unsigned char *)malloc (sizeof (unsigned char) * w
|
||||
* h * components);
|
||||
if (!surface) {
|
||||
DBG( 1, "Escl Png : texels Memory allocation problem\n");
|
||||
status = SANE_STATUS_NO_MEM;
|
||||
goto close_file;
|
||||
}
|
||||
png_bytep *row_pointers;
|
||||
// setup a pointer array. Each one points at the begening of a row.
|
||||
row_pointers = (png_bytep *)malloc (sizeof (png_bytep) * h);
|
||||
if (!row_pointers) {
|
||||
DBG( 1, "Escl Png : row_pointers Memory allocation problem\n");
|
||||
free(surface);
|
||||
status = SANE_STATUS_NO_MEM;
|
||||
goto close_file;
|
||||
}
|
||||
for (i = 0; i < h; ++i)
|
||||
{
|
||||
row_pointers[i] = (png_bytep)(surface +
|
||||
((h - (i + 1)) * w * components));
|
||||
}
|
||||
// read pixel data using row pointers
|
||||
png_read_image (png_ptr, row_pointers);
|
||||
|
||||
// If necessary, trim the image.
|
||||
surface = escl_crop_surface(scanner, surface, w, h, components, width, height);
|
||||
if (!surface) {
|
||||
DBG( 1, "Escl Png : Surface Memory allocation problem\n");
|
||||
status = SANE_STATUS_NO_MEM;
|
||||
goto close_file;
|
||||
}
|
||||
|
||||
free (row_pointers);
|
||||
|
||||
close_file:
|
||||
if (scanner->tmp)
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
return (status);
|
||||
}
|
||||
#else
|
||||
|
||||
SANE_Status
|
||||
get_PNG_data(capabilities_t __sane_unused__ *scanner,
|
||||
int __sane_unused__ *width,
|
||||
int __sane_unused__ *height,
|
||||
int __sane_unused__ *bps)
|
||||
{
|
||||
return (SANE_STATUS_INVAL);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -21,6 +21,9 @@
|
|||
|
||||
This file implements a SANE backend for eSCL scanners. */
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#include "escl.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
@ -45,7 +48,6 @@ escl_scanner(SANE_String_Const name, char *result)
|
|||
|
||||
if (name == NULL || result == NULL)
|
||||
return;
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
CURL_CALL:
|
||||
curl_handle = curl_easy_init();
|
||||
if (curl_handle != NULL) {
|
||||
|
@ -54,7 +56,9 @@ CURL_CALL:
|
|||
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);
|
||||
}
|
||||
|
@ -68,5 +72,4 @@ CURL_CALL:
|
|||
}
|
||||
curl_easy_cleanup(curl_handle);
|
||||
}
|
||||
curl_global_cleanup();
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
|
||||
This file implements a SANE backend for eSCL scanners. */
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#include "escl.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -65,7 +68,6 @@ escl_scan(capabilities_t __sane_unused__ *scanner, SANE_String_Const name, char
|
|||
|
||||
if (name == NULL)
|
||||
return (SANE_STATUS_NO_MEM);
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
curl_handle = curl_easy_init();
|
||||
if (curl_handle != NULL) {
|
||||
strcpy(scan_cmd, name);
|
||||
|
@ -73,7 +75,9 @@ escl_scan(capabilities_t __sane_unused__ *scanner, SANE_String_Const name, char
|
|||
strcat(scan_cmd, result);
|
||||
strcat(scan_cmd, scanner_start);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_URL, scan_cmd);
|
||||
if (strncmp(name, "https", 5) == 0) {
|
||||
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);
|
||||
}
|
||||
|
@ -90,7 +94,6 @@ escl_scan(capabilities_t __sane_unused__ *scanner, SANE_String_Const name, char
|
|||
}
|
||||
else
|
||||
status = SANE_STATUS_NO_MEM;
|
||||
curl_global_cleanup();
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
|
||||
This file implements a SANE backend for eSCL scanners. */
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#include "escl.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -50,7 +53,7 @@ memory_callback_s(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(1, "not enough memory (realloc returned NULL)\n");
|
||||
return (0);
|
||||
}
|
||||
mem->memory = str;
|
||||
|
@ -132,19 +135,20 @@ escl_status(SANE_String_Const name)
|
|||
return (SANE_STATUS_NO_MEM);
|
||||
var->memory = malloc(1);
|
||||
var->size = 0;
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
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);
|
||||
}
|
||||
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) {
|
||||
fprintf(stderr, "THERE IS NO SCANNER\n");
|
||||
DBG( 1, "The scanner didn't respond.\n");
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto clean_data;
|
||||
}
|
||||
|
@ -168,6 +172,5 @@ clean_data:
|
|||
curl_easy_cleanup(curl_handle);
|
||||
free(var->memory);
|
||||
free(var);
|
||||
curl_global_cleanup();
|
||||
return (status);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2019 Touboul Nathane
|
||||
Copyright (C) 2019 Thierry HUCHARD <thierry@ordissimo.com>
|
||||
|
||||
This file is part of the SANE package.
|
||||
|
||||
SANE is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
SANE is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with sane; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
This file implements a SANE backend for eSCL scanners. */
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#include "escl.h"
|
||||
|
||||
#include "../include/sane/sanei.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if(defined HAVE_TIFFIO_H)
|
||||
#include <tiffio.h>
|
||||
#endif
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
|
||||
#if(defined HAVE_TIFFIO_H)
|
||||
|
||||
/**
|
||||
* \fn SANE_Status escl_sane_decompressor(escl_sane_t *handler)
|
||||
* \brief Function that aims to decompress the png image to SANE be able to read the image.
|
||||
* This function is called in the "sane_read" function.
|
||||
*
|
||||
* \return SANE_STATUS_GOOD (if everything is OK, otherwise, SANE_STATUS_NO_MEM/SANE_STATUS_INVAL)
|
||||
*/
|
||||
SANE_Status
|
||||
get_TIFF_data(capabilities_t *scanner, int *width, int *height, int *bps)
|
||||
{
|
||||
TIFF* tif = NULL;
|
||||
uint32 w = 0;
|
||||
uint32 h = 0;
|
||||
unsigned char *surface = NULL; /* image data*/
|
||||
int components = 4;
|
||||
uint32 npixels = 0;
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
|
||||
lseek(fileno(scanner->tmp), 0, SEEK_SET);
|
||||
tif = TIFFFdOpen(fileno(scanner->tmp), "temp", "r");
|
||||
if (!tif) {
|
||||
DBG( 1, "Escl Tiff : Can not open, or not a TIFF file.\n");
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto close_file;
|
||||
}
|
||||
|
||||
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
|
||||
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
|
||||
npixels = w * h;
|
||||
surface = (unsigned char*) malloc(npixels * sizeof (uint32));
|
||||
if (surface != NULL)
|
||||
{
|
||||
DBG( 1, "Escl Tiff : raster Memory allocation problem.\n");
|
||||
status = SANE_STATUS_INVAL;
|
||||
goto close_tiff;
|
||||
}
|
||||
|
||||
if (!TIFFReadRGBAImage(tif, w, h, (uint32 *)surface, 0))
|
||||
{
|
||||
DBG( 1, "Escl Tiff : Problem reading image data.\n");
|
||||
status = SANE_STATUS_INVAL;
|
||||
free(surface);
|
||||
goto close_tiff;
|
||||
}
|
||||
|
||||
*bps = components;
|
||||
|
||||
// If necessary, trim the image.
|
||||
surface = escl_crop_surface(scanner, surface, w, h, components, width, height);
|
||||
if (!surface) {
|
||||
DBG( 1, "Escl Tiff : Surface Memory allocation problem\n");
|
||||
status = SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
close_tiff:
|
||||
TIFFClose(tif);
|
||||
close_file:
|
||||
if (scanner->tmp)
|
||||
fclose(scanner->tmp);
|
||||
scanner->tmp = NULL;
|
||||
return (status);
|
||||
}
|
||||
#else
|
||||
|
||||
SANE_Status
|
||||
get_TIFF_data(capabilities_t __sane_unused__ *scanner,
|
||||
int __sane_unused__ *w,
|
||||
int __sane_unused__ *h,
|
||||
int __sane_unused__ *bps)
|
||||
{
|
||||
return (SANE_STATUS_INVAL);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -383,6 +383,9 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
|
|||
|
||||
#define get_IN_op_halt(in) getbitfield(in+0x7a, 1, 7)
|
||||
|
||||
#define get_IN_return_path(in) getbitfield(in+0x7c, 1, 7)
|
||||
#define get_IN_energy_star3(in) getbitfield(in+0x7c, 1, 6)
|
||||
|
||||
/* ==================================================================== */
|
||||
/* page codes used by mode_sense and mode_select */
|
||||
#define MS_pc_unk 0x2c /* Used by iX500 */
|
||||
|
@ -763,6 +766,7 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
|
|||
#define get_GHS_fb_open(in) getbitfield(in+0x03, 1, 3)
|
||||
#define get_GHS_paper_end(in) getbitfield(in+0x03, 1, 2)
|
||||
#define get_GHS_fb_on(in) getbitfield(in+0x03, 1, 1)
|
||||
#define get_GHS_exit(in) getbitfield(in+0x03, 1, 0)
|
||||
|
||||
#define get_GHS_sleep(in) getbitfield(in+0x04, 1, 7)
|
||||
#define get_GHS_clean(in) getbitfield(in+0x04, 1, 6)
|
||||
|
@ -823,7 +827,8 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
|
|||
#define SCANNER_CONTROL_len 10
|
||||
|
||||
#define set_SC_ric(icb, val) setbitfield(icb + 1, 1, 4, val)
|
||||
#define set_SC_function(icb, val) setbitfield(icb + 1, 0xf, 0, val)
|
||||
#define set_SC_function_1(icb, val) setbitfield(icb + 1, 0xf, 0, val)
|
||||
#define set_SC_function_2(icb, val) icb[2] = (val >> 4)
|
||||
#define SC_function_adf 0x00
|
||||
#define SC_function_fb 0x01
|
||||
#define SC_function_fb_hs 0x02
|
||||
|
@ -836,6 +841,9 @@ putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes)
|
|||
#define SC_function_scan_complete 0x09
|
||||
#define SC_function_eject_complete 0x0a
|
||||
#define SC_function_manual_feed 0x0c
|
||||
#define SC_function_mfeed 0x0f
|
||||
#define SC_function_continuous 0x1f
|
||||
#define SC_function_rpath 0x2f
|
||||
|
||||
/* used with SC_function_panel */
|
||||
#define set_SC_led_eb(icb, val) setbitfield(icb + 5, 1, 7, val)
|
||||
|
|
|
@ -603,8 +603,12 @@
|
|||
v134 2019-02-23, MAN
|
||||
- rewrite init_vpd for scanners which fail to report
|
||||
overscan correctly
|
||||
v135 2019-11-10, MAN
|
||||
v135 2019-11-10, MAN (SANE 1.0.29)
|
||||
- set has_MS_lamp=0 for fi-72x0, bug #134
|
||||
v136 2020-02-07, MAN
|
||||
- add support for fi-800R
|
||||
- add support for card scanning slot (Return Path)
|
||||
- fix bug with reading hardware sensors on first invocation
|
||||
|
||||
SANE FLOW DIAGRAM
|
||||
|
||||
|
@ -654,7 +658,7 @@
|
|||
#include "fujitsu.h"
|
||||
|
||||
#define DEBUG 1
|
||||
#define BUILD 134
|
||||
#define BUILD 136
|
||||
|
||||
/* values for SANE_DEBUG_FUJITSU env var:
|
||||
- errors 5
|
||||
|
@ -678,6 +682,9 @@
|
|||
#define STRING_ADFFRONT SANE_I18N("ADF Front")
|
||||
#define STRING_ADFBACK SANE_I18N("ADF Back")
|
||||
#define STRING_ADFDUPLEX SANE_I18N("ADF Duplex")
|
||||
#define STRING_CARDFRONT SANE_I18N("Card Front")
|
||||
#define STRING_CARDBACK SANE_I18N("Card Back")
|
||||
#define STRING_CARDDUPLEX SANE_I18N("Card Duplex")
|
||||
|
||||
#define STRING_LINEART SANE_VALUE_SCAN_MODE_LINEART
|
||||
#define STRING_HALFTONE SANE_VALUE_SCAN_MODE_HALFTONE
|
||||
|
@ -1821,6 +1828,12 @@ init_vpd (struct fujitsu *s)
|
|||
DBG (15, " object position halt: %d\n", s->has_op_halt);
|
||||
}
|
||||
|
||||
if (payload_off >= 0x7c) {
|
||||
s->has_return_path = get_IN_return_path(in);
|
||||
DBG (15, " return path (card) scanning: %d\n", s->has_return_path);
|
||||
DBG (15, " energy star 3: %d\n", get_IN_energy_star3(in));
|
||||
}
|
||||
|
||||
DBG (10, "init_vpd: finish\n");
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
|
@ -2498,6 +2511,8 @@ init_user (struct fujitsu *s)
|
|||
s->source = SOURCE_FLATBED;
|
||||
else if(s->has_adf)
|
||||
s->source = SOURCE_ADF_FRONT;
|
||||
else if(s->has_return_path)
|
||||
s->source = SOURCE_CARD_FRONT;
|
||||
|
||||
/* scan mode */
|
||||
if(s->can_mode[MODE_LINEART])
|
||||
|
@ -2875,6 +2890,16 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
|
|||
s->source_list[i++]=STRING_ADFDUPLEX;
|
||||
}
|
||||
}
|
||||
if(s->has_return_path){
|
||||
s->source_list[i++]=STRING_CARDFRONT;
|
||||
|
||||
if(s->has_back){
|
||||
s->source_list[i++]=STRING_CARDBACK;
|
||||
}
|
||||
if(s->has_duplex){
|
||||
s->source_list[i++]=STRING_CARDDUPLEX;
|
||||
}
|
||||
}
|
||||
s->source_list[i]=NULL;
|
||||
|
||||
opt->name = SANE_NAME_SCAN_SOURCE;
|
||||
|
@ -3049,7 +3074,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
|
|||
opt->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
opt->constraint.range = &s->paper_x_range;
|
||||
|
||||
if(s->has_adf){
|
||||
if(s->has_adf || s->has_return_path){
|
||||
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||||
if(s->source == SOURCE_FLATBED){
|
||||
opt->cap |= SANE_CAP_INACTIVE;
|
||||
|
@ -3076,7 +3101,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
|
|||
opt->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
opt->constraint.range = &s->paper_y_range;
|
||||
|
||||
if(s->has_adf){
|
||||
if(s->has_adf || s->has_return_path){
|
||||
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||||
if(s->source == SOURCE_FLATBED){
|
||||
opt->cap |= SANE_CAP_INACTIVE;
|
||||
|
@ -4474,6 +4499,18 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
|
|||
opt->cap = SANE_CAP_INACTIVE;
|
||||
}
|
||||
|
||||
if(option==OPT_CARD_LOADED){
|
||||
opt->name = "card-loaded";
|
||||
opt->title = SANE_I18N ("Card loaded");
|
||||
opt->desc = SANE_I18N ("Card slot contains paper");
|
||||
opt->type = SANE_TYPE_BOOL;
|
||||
opt->unit = SANE_UNIT_NONE;
|
||||
if (s->has_cmd_hw_status && s->has_return_path)
|
||||
opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
|
||||
else
|
||||
opt->cap = SANE_CAP_INACTIVE;
|
||||
}
|
||||
|
||||
if(option==OPT_SLEEP){
|
||||
opt->name = "power-save";
|
||||
opt->title = SANE_I18N ("Power saving");
|
||||
|
@ -4697,6 +4734,15 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
|
|||
else if(s->source == SOURCE_ADF_DUPLEX){
|
||||
strcpy (val, STRING_ADFDUPLEX);
|
||||
}
|
||||
else if(s->source == SOURCE_CARD_FRONT){
|
||||
strcpy (val, STRING_CARDFRONT);
|
||||
}
|
||||
else if(s->source == SOURCE_CARD_BACK){
|
||||
strcpy (val, STRING_CARDBACK);
|
||||
}
|
||||
else if(s->source == SOURCE_CARD_DUPLEX){
|
||||
strcpy (val, STRING_CARDDUPLEX);
|
||||
}
|
||||
return SANE_STATUS_GOOD;
|
||||
|
||||
case OPT_MODE:
|
||||
|
@ -5215,6 +5261,11 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
|
|||
*val_p = s->hw_adf_open;
|
||||
return ret;
|
||||
|
||||
case OPT_CARD_LOADED:
|
||||
ret = get_hardware_status(s,option);
|
||||
*val_p = s->hw_card_loaded;
|
||||
return ret;
|
||||
|
||||
case OPT_SLEEP:
|
||||
ret = get_hardware_status(s,option);
|
||||
*val_p = s->hw_sleep;
|
||||
|
@ -5323,6 +5374,15 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
|
|||
else if (!strcmp (val, STRING_ADFDUPLEX)) {
|
||||
tmp = SOURCE_ADF_DUPLEX;
|
||||
}
|
||||
else if (!strcmp (val, STRING_CARDFRONT)) {
|
||||
tmp = SOURCE_CARD_FRONT;
|
||||
}
|
||||
else if (!strcmp (val, STRING_CARDBACK)) {
|
||||
tmp = SOURCE_CARD_BACK;
|
||||
}
|
||||
else if (!strcmp (val, STRING_CARDDUPLEX)) {
|
||||
tmp = SOURCE_CARD_DUPLEX;
|
||||
}
|
||||
else{
|
||||
tmp = SOURCE_FLATBED;
|
||||
}
|
||||
|
@ -5912,12 +5972,12 @@ get_hardware_status (struct fujitsu *s, SANE_Int option)
|
|||
|
||||
/* only run this if frontend has already read the last time we got it */
|
||||
/* or if we don't care for such bookkeeping (private use) */
|
||||
if (!option || s->hw_read[option-OPT_TOP]) {
|
||||
if (!option || !s->hw_data_avail[option-OPT_TOP]) {
|
||||
|
||||
DBG (15, "get_hardware_status: running\n");
|
||||
|
||||
/* mark all values as unread */
|
||||
memset(s->hw_read,0,sizeof(s->hw_read));
|
||||
/* mark all values as available */
|
||||
memset(s->hw_data_avail,1,sizeof(s->hw_data_avail));
|
||||
|
||||
if (s->has_cmd_hw_status){
|
||||
unsigned char cmd[GET_HW_STATUS_len];
|
||||
|
@ -5950,6 +6010,7 @@ get_hardware_status (struct fujitsu *s, SANE_Int option)
|
|||
s->hw_hopper = get_GHS_hopper(in);
|
||||
s->hw_omr = get_GHS_omr(in);
|
||||
s->hw_adf_open = get_GHS_adf_open(in);
|
||||
s->hw_card_loaded = get_GHS_exit(in);
|
||||
|
||||
s->hw_sleep = get_GHS_sleep(in);
|
||||
s->hw_send_sw = get_GHS_send_sw(in);
|
||||
|
@ -6015,7 +6076,7 @@ get_hardware_status (struct fujitsu *s, SANE_Int option)
|
|||
}
|
||||
|
||||
if(option)
|
||||
s->hw_read[option-OPT_TOP] = 1;
|
||||
s->hw_data_avail[option-OPT_TOP] = 0;
|
||||
|
||||
DBG (10, "get_hardware_status: finish\n");
|
||||
|
||||
|
@ -6905,8 +6966,8 @@ sane_start (SANE_Handle handle)
|
|||
}
|
||||
|
||||
/* low mem mode messes up the side marker, reset it */
|
||||
if(s->source == SOURCE_ADF_DUPLEX && s->low_mem
|
||||
&& s->eof_tx[SIDE_FRONT] && s->eof_tx[SIDE_BACK]
|
||||
if((s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX)
|
||||
&& s->low_mem && s->eof_tx[SIDE_FRONT] && s->eof_tx[SIDE_BACK]
|
||||
){
|
||||
s->side = SIDE_BACK;
|
||||
}
|
||||
|
@ -6915,7 +6976,7 @@ sane_start (SANE_Handle handle)
|
|||
if(!s->started){
|
||||
|
||||
/* load side marker */
|
||||
if(s->source == SOURCE_ADF_BACK){
|
||||
if(s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK){
|
||||
s->side = SIDE_BACK;
|
||||
}
|
||||
else{
|
||||
|
@ -6936,6 +6997,12 @@ sane_start (SANE_Handle handle)
|
|||
DBG (5, "sane_start: ERROR: cannot control fb, ignoring\n");
|
||||
}
|
||||
}
|
||||
else if(s->source == SOURCE_CARD_FRONT || s->source == SOURCE_CARD_BACK || s->source == SOURCE_CARD_DUPLEX){
|
||||
ret = scanner_control(s, SC_function_rpath);
|
||||
if (ret != SANE_STATUS_GOOD) {
|
||||
DBG (5, "sane_start: ERROR: cannot control rp, ignoring\n");
|
||||
}
|
||||
}
|
||||
else{
|
||||
ret = scanner_control(s, SC_function_adf);
|
||||
if (ret != SANE_STATUS_GOOD) {
|
||||
|
@ -7038,7 +7105,7 @@ sane_start (SANE_Handle handle)
|
|||
}
|
||||
}
|
||||
/* if already running, duplex needs to switch sides */
|
||||
else if(s->source == SOURCE_ADF_DUPLEX){
|
||||
else if(s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX){
|
||||
s->side = !s->side;
|
||||
}
|
||||
|
||||
|
@ -7047,7 +7114,7 @@ sane_start (SANE_Handle handle)
|
|||
/* otherwise buffered back page will be lost */
|
||||
/* ingest paper with adf (no-op for fb) */
|
||||
/* dont call object pos or scan on back side of duplex scan */
|
||||
if(s->side == SIDE_FRONT || s->source == SOURCE_ADF_BACK){
|
||||
if(s->side == SIDE_FRONT || s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK){
|
||||
|
||||
s->bytes_rx[0]=0;
|
||||
s->bytes_rx[1]=0;
|
||||
|
@ -7095,7 +7162,7 @@ sane_start (SANE_Handle handle)
|
|||
}
|
||||
|
||||
/* store the number of front bytes */
|
||||
if ( s->source != SOURCE_ADF_BACK ){
|
||||
if ( s->source != SOURCE_ADF_BACK && s->source != SOURCE_CARD_BACK ){
|
||||
s->bytes_tot[SIDE_FRONT] = s->s_params.bytes_per_line * s->s_params.lines;
|
||||
s->buff_tot[SIDE_FRONT] = s->buffer_size;
|
||||
|
||||
|
@ -7114,13 +7181,14 @@ sane_start (SANE_Handle handle)
|
|||
}
|
||||
|
||||
/* store the number of back bytes */
|
||||
if ( s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_ADF_BACK ){
|
||||
if ( s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_ADF_BACK
|
||||
|| s->source == SOURCE_CARD_DUPLEX || s->source == SOURCE_CARD_BACK ){
|
||||
s->bytes_tot[SIDE_BACK] = s->s_params.bytes_per_line * s->s_params.lines;
|
||||
s->buff_tot[SIDE_BACK] = s->bytes_tot[SIDE_BACK];
|
||||
|
||||
/* the back buffer is normally very large, but some scanners or
|
||||
* option combinations dont need it, so we make a small one */
|
||||
if(s->low_mem || s->source == SOURCE_ADF_BACK
|
||||
if(s->low_mem || s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK
|
||||
|| s->duplex_interlace == DUPLEX_INTERLACE_NONE)
|
||||
s->buff_tot[SIDE_BACK] = s->buffer_size;
|
||||
}
|
||||
|
@ -7308,13 +7376,14 @@ scanner_control (struct fujitsu *s, int function)
|
|||
|
||||
memset(cmd,0,cmdLen);
|
||||
set_SCSI_opcode(cmd, SCANNER_CONTROL_code);
|
||||
set_SC_function (cmd, function);
|
||||
set_SC_function_1 (cmd, function);
|
||||
set_SC_function_2 (cmd, function);
|
||||
|
||||
DBG (15, "scanner_control: function %d\n",function);
|
||||
|
||||
/* don't really need to ask for adf if that's the only option */
|
||||
/* doing so causes the 3091 to complain */
|
||||
if(function == SC_function_adf && !s->has_flatbed){
|
||||
if(function == SC_function_adf && !s->has_flatbed && !s->has_return_path){
|
||||
DBG (10, "scanner_control: adf function not required\n");
|
||||
return ret;
|
||||
}
|
||||
|
@ -7486,7 +7555,7 @@ set_window (struct fujitsu *s)
|
|||
set_WPDB_wdblen(header, SW_desc_len);
|
||||
|
||||
/* init the window block */
|
||||
if (s->source == SOURCE_ADF_BACK) {
|
||||
if (s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK) {
|
||||
set_WD_wid (desc1, WD_wid_back);
|
||||
}
|
||||
else{
|
||||
|
@ -7675,7 +7744,7 @@ set_window (struct fujitsu *s)
|
|||
}
|
||||
|
||||
/* when in duplex mode, copy first desc block into second */
|
||||
if (s->source == SOURCE_ADF_DUPLEX) {
|
||||
if (s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX) {
|
||||
memcpy (desc2, desc1, SW_desc_len);
|
||||
|
||||
set_WD_wid (desc2, WD_wid_back);
|
||||
|
@ -7823,7 +7892,7 @@ get_pixelsize(struct fujitsu *s, int actual)
|
|||
}
|
||||
|
||||
/*
|
||||
* Issues the SCSI OBJECT POSITION command if an ADF is in use.
|
||||
* Issues the SCSI OBJECT POSITION command if an ADF or card scanner is in use.
|
||||
*/
|
||||
static SANE_Status
|
||||
object_position (struct fujitsu *s, int action)
|
||||
|
@ -7880,9 +7949,9 @@ start_scan (struct fujitsu *s)
|
|||
|
||||
DBG (10, "start_scan: start\n");
|
||||
|
||||
if (s->source != SOURCE_ADF_DUPLEX) {
|
||||
if (s->source != SOURCE_ADF_DUPLEX && s->source != SOURCE_CARD_DUPLEX) {
|
||||
outLen--;
|
||||
if(s->source == SOURCE_ADF_BACK) {
|
||||
if(s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK) {
|
||||
out[0] = WD_wid_back;
|
||||
}
|
||||
}
|
||||
|
@ -7983,7 +8052,8 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len
|
|||
|
||||
/* swap sides if user asked for low-mem mode, we are duplexing,
|
||||
* and there is data waiting on the other side */
|
||||
if(s->low_mem && s->source == SOURCE_ADF_DUPLEX
|
||||
if(s->low_mem
|
||||
&& (s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX)
|
||||
&& (s->bytes_rx[!s->side] > s->bytes_tx[!s->side]
|
||||
|| (s->eof_rx[!s->side] && !s->eof_tx[!s->side])
|
||||
)
|
||||
|
@ -8013,7 +8083,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len
|
|||
} /* end 3091 */
|
||||
|
||||
/* alternating jpeg duplex interlacing */
|
||||
else if(s->source == SOURCE_ADF_DUPLEX
|
||||
else if((s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX)
|
||||
&& s->s_params.format == SANE_FRAME_JPEG
|
||||
&& s->jpeg_interlace == JPEG_INTERLACE_ALT
|
||||
){
|
||||
|
@ -8025,7 +8095,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len
|
|||
} /* end alt jpeg */
|
||||
|
||||
/* alternating pnm duplex interlacing */
|
||||
else if(s->source == SOURCE_ADF_DUPLEX
|
||||
else if((s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX)
|
||||
&& s->s_params.format != SANE_FRAME_JPEG
|
||||
&& s->duplex_interlace == DUPLEX_INTERLACE_ALT
|
||||
){
|
||||
|
@ -8080,7 +8150,8 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len
|
|||
|
||||
/* swap sides if user asked for low-mem mode, we are duplexing,
|
||||
* and there is data waiting on the other side */
|
||||
if(s->low_mem && s->source == SOURCE_ADF_DUPLEX
|
||||
if(s->low_mem
|
||||
&& (s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_CARD_DUPLEX)
|
||||
&& (s->bytes_rx[!s->side] > s->bytes_tx[!s->side]
|
||||
|| (s->eof_rx[!s->side] && !s->eof_tx[!s->side])
|
||||
)
|
||||
|
@ -9291,6 +9362,10 @@ sense_handler (int fd, unsigned char * sensed_data, void *arg)
|
|||
DBG (5, "Medium error: Carrier sheet\n");
|
||||
return SANE_STATUS_JAMMED;
|
||||
}
|
||||
if (0x0c == ascq) {
|
||||
DBG (5, "Medium error: ADF blocked by card\n");
|
||||
return SANE_STATUS_JAMMED;
|
||||
}
|
||||
if (0x10 == ascq) {
|
||||
DBG (5, "Medium error: no ink cartridge\n");
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
|
@ -10092,7 +10167,9 @@ buffer_deskew(struct fujitsu *s, int side)
|
|||
DBG (10, "buffer_deskew: start\n");
|
||||
|
||||
/*only find skew on first image from a page, or if first image had error */
|
||||
if(s->side == SIDE_FRONT || s->source == SOURCE_ADF_BACK || s->deskew_stat){
|
||||
if(s->side == SIDE_FRONT
|
||||
|| s->source == SOURCE_ADF_BACK || s->source == SOURCE_CARD_BACK
|
||||
|| s->deskew_stat){
|
||||
|
||||
s->deskew_stat = sanei_magic_findSkew(
|
||||
&s->s_params,s->buffers[side],s->resolution_x,s->resolution_y,
|
||||
|
|
|
@ -255,3 +255,6 @@ usb 0x04c5 0x1522
|
|||
|
||||
#ScanSnap iX1500
|
||||
usb 0x04c5 0x159f
|
||||
|
||||
#fi-800R
|
||||
usb 0x04c5 0x15fc
|
||||
|
|
|
@ -112,6 +112,7 @@ enum fujitsu_Option
|
|||
OPT_HOPPER,
|
||||
OPT_OMR,
|
||||
OPT_ADF_OPEN,
|
||||
OPT_CARD_LOADED,
|
||||
OPT_SLEEP,
|
||||
OPT_SEND_SW,
|
||||
OPT_MANUAL_FEED,
|
||||
|
@ -277,6 +278,7 @@ struct fujitsu
|
|||
int has_comp_JPG2;
|
||||
int has_comp_JPG3;
|
||||
int has_op_halt;
|
||||
int has_return_path;
|
||||
|
||||
/*FIXME: more endorser data? */
|
||||
int endorser_type_f;
|
||||
|
@ -361,7 +363,7 @@ struct fujitsu
|
|||
|
||||
/*mode group*/
|
||||
SANE_String_Const mode_list[7];
|
||||
SANE_String_Const source_list[5];
|
||||
SANE_String_Const source_list[8];
|
||||
|
||||
SANE_Int res_list[17];
|
||||
SANE_Range res_range;
|
||||
|
@ -599,6 +601,7 @@ struct fujitsu
|
|||
int hw_hopper;
|
||||
int hw_omr;
|
||||
int hw_adf_open;
|
||||
int hw_card_loaded;
|
||||
|
||||
int hw_sleep;
|
||||
int hw_send_sw;
|
||||
|
@ -618,7 +621,7 @@ struct fujitsu
|
|||
int hw_density_sw;
|
||||
|
||||
/* values which are used to track the frontend's access to sensors */
|
||||
char hw_read[NUM_OPTIONS-OPT_TOP];
|
||||
char hw_data_avail[NUM_OPTIONS-OPT_TOP];
|
||||
};
|
||||
|
||||
#define CONNECTION_SCSI 0 /* SCSI interface */
|
||||
|
@ -631,6 +634,9 @@ struct fujitsu
|
|||
#define SOURCE_ADF_FRONT 1
|
||||
#define SOURCE_ADF_BACK 2
|
||||
#define SOURCE_ADF_DUPLEX 3
|
||||
#define SOURCE_CARD_FRONT 4
|
||||
#define SOURCE_CARD_BACK 5
|
||||
#define SOURCE_CARD_DUPLEX 6
|
||||
|
||||
#define COMP_NONE WD_cmp_NONE
|
||||
#define COMP_JPEG WD_cmp_JPG1
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
# Hewlett Packard ScanJet 2400c
|
||||
usb 0x03f0 0x0a01
|
||||
|
||||
# Hewlett Packard ScanJet 3670c/3690c
|
||||
# Hewlett Packard ScanJet 3670/3690c
|
||||
usb 0x03f0 0x1405
|
||||
|
||||
# Plustek OpticPro ST24
|
||||
|
|
|
@ -63,8 +63,7 @@ struct Genesys_Calibration_Cache
|
|||
Genesys_Frontend frontend;
|
||||
Genesys_Sensor sensor;
|
||||
|
||||
size_t calib_pixels = 0;
|
||||
size_t calib_channels = 0;
|
||||
ScanSession session;
|
||||
size_t average_size = 0;
|
||||
std::vector<std::uint16_t> white_average_data;
|
||||
std::vector<std::uint16_t> dark_average_data;
|
||||
|
@ -75,8 +74,7 @@ struct Genesys_Calibration_Cache
|
|||
last_calibration == other.last_calibration &&
|
||||
frontend == other.frontend &&
|
||||
sensor == other.sensor &&
|
||||
calib_pixels == other.calib_pixels &&
|
||||
calib_channels == other.calib_channels &&
|
||||
session == other.session &&
|
||||
average_size == other.average_size &&
|
||||
white_average_data == other.white_average_data &&
|
||||
dark_average_data == other.dark_average_data;
|
||||
|
@ -94,8 +92,7 @@ void serialize(Stream& str, Genesys_Calibration_Cache& x)
|
|||
serialize_newline(str);
|
||||
serialize(str, x.sensor);
|
||||
serialize_newline(str);
|
||||
serialize(str, x.calib_pixels);
|
||||
serialize(str, x.calib_channels);
|
||||
serialize(str, x.session);
|
||||
serialize(str, x.average_size);
|
||||
serialize_newline(str);
|
||||
serialize(str, x.white_average_data);
|
||||
|
|
|
@ -70,11 +70,10 @@ public:
|
|||
Genesys_Register_Set* regs, int* channels,
|
||||
int* total_size) const = 0;
|
||||
|
||||
virtual void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const = 0;
|
||||
virtual void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const = 0;
|
||||
virtual void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const = 0;
|
||||
virtual void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const = 0;
|
||||
|
||||
/** Set up registers for a scan. Similar to init_regs_for_scan except that the session is
|
||||
already computed from the session
|
||||
|
@ -98,7 +97,6 @@ public:
|
|||
*/
|
||||
virtual void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const = 0;
|
||||
|
||||
virtual void search_start_position(Genesys_Device* dev) const = 0;
|
||||
virtual void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const = 0;
|
||||
virtual void coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
|
@ -134,11 +132,6 @@ public:
|
|||
|
||||
/// eject document from scanner
|
||||
virtual void eject_document(Genesys_Device* dev) const = 0;
|
||||
/**
|
||||
* search for an black or white area in forward or reverse
|
||||
* direction */
|
||||
virtual void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
bool forward, bool black) const = 0;
|
||||
|
||||
/// move scanning head to transparency adapter
|
||||
virtual void move_to_ta(Genesys_Device* dev) const = 0;
|
||||
|
@ -159,6 +152,16 @@ public:
|
|||
|
||||
/// cold boot init function
|
||||
virtual void asic_boot(Genesys_Device* dev, bool cold) const = 0;
|
||||
|
||||
/// checks if specific scan head is at home position
|
||||
virtual bool is_head_home(Genesys_Device& dev, ScanHeadId scan_head) const = 0;
|
||||
|
||||
/// enables or disables XPA slider motor
|
||||
virtual void set_xpa_lamp_power(Genesys_Device& dev, bool set) const = 0;
|
||||
|
||||
/// enables or disables XPA slider motor
|
||||
virtual void set_motor_mode(Genesys_Device& dev, Genesys_Register_Set& regs,
|
||||
MotorMode mode) const = 0;
|
||||
};
|
||||
|
||||
} // namespace genesys
|
||||
|
|
|
@ -0,0 +1,234 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
|
||||
|
||||
This file is part of the SANE package.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
|
||||
#include "command_set_common.h"
|
||||
#include "low.h"
|
||||
|
||||
namespace genesys {
|
||||
|
||||
CommandSetCommon::~CommandSetCommon() = default;
|
||||
|
||||
bool CommandSetCommon::is_head_home(Genesys_Device& dev, ScanHeadId scan_head) const
|
||||
{
|
||||
struct HeadSettings {
|
||||
ModelId model_id;
|
||||
ScanHeadId scan_head;
|
||||
GenesysRegisterSettingSet regs;
|
||||
};
|
||||
|
||||
HeadSettings settings[] = {
|
||||
{ ModelId::CANON_8600F,
|
||||
ScanHeadId::PRIMARY, {
|
||||
{ 0x6c, 0x20, 0x60 },
|
||||
{ 0xa6, 0x00, 0x01 },
|
||||
}
|
||||
},
|
||||
{ ModelId::CANON_8600F,
|
||||
ScanHeadId::SECONDARY, {
|
||||
{ 0x6c, 0x00, 0x60 },
|
||||
{ 0xa6, 0x01, 0x01 },
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
for (const auto& setting : settings) {
|
||||
if (setting.model_id == dev.model->model_id &&
|
||||
setting.scan_head == scan_head)
|
||||
{
|
||||
auto reg_backup = apply_reg_settings_to_device_with_backup(dev, setting.regs);
|
||||
auto status = scanner_read_status(dev);
|
||||
apply_reg_settings_to_device(dev, reg_backup);
|
||||
return status.is_at_home;
|
||||
}
|
||||
}
|
||||
|
||||
auto status = scanner_read_status(dev);
|
||||
return status.is_at_home;
|
||||
}
|
||||
|
||||
void CommandSetCommon::set_xpa_lamp_power(Genesys_Device& dev, bool set) const
|
||||
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
|
||||
struct LampSettings {
|
||||
ModelId model_id;
|
||||
ScanMethod scan_method;
|
||||
GenesysRegisterSettingSet regs_on;
|
||||
GenesysRegisterSettingSet regs_off;
|
||||
};
|
||||
|
||||
// FIXME: BUG: we're not clearing the registers to the previous state when returning back when
|
||||
// turning off the lamp
|
||||
LampSettings settings[] = {
|
||||
{ ModelId::CANON_4400F, ScanMethod::TRANSPARENCY, {}, {} },
|
||||
{ ModelId::CANON_8400F, ScanMethod::TRANSPARENCY, {
|
||||
{ 0xa6, 0x34, 0xf4 },
|
||||
}, {
|
||||
{ 0xa6, 0x40, 0x70 },
|
||||
}
|
||||
},
|
||||
{ ModelId::CANON_8400F, ScanMethod::TRANSPARENCY_INFRARED, {
|
||||
{ 0x6c, 0x40, 0x40 },
|
||||
{ 0xa6, 0x01, 0xff },
|
||||
}, {
|
||||
{ 0x6c, 0x00, 0x40 },
|
||||
{ 0xa6, 0x00, 0xff },
|
||||
}
|
||||
},
|
||||
{ ModelId::CANON_8600F, ScanMethod::TRANSPARENCY, {
|
||||
{ 0xa6, 0x34, 0xf4 },
|
||||
{ 0xa7, 0xe0, 0xe0 },
|
||||
}, {
|
||||
{ 0xa6, 0x40, 0x70 },
|
||||
}
|
||||
},
|
||||
{ ModelId::CANON_8600F, ScanMethod::TRANSPARENCY_INFRARED, {
|
||||
{ 0xa6, 0x00, 0xc0 },
|
||||
{ 0xa7, 0xe0, 0xe0 },
|
||||
{ 0x6c, 0x80, 0x80 },
|
||||
}, {
|
||||
{ 0xa6, 0x00, 0xc0 },
|
||||
{ 0x6c, 0x00, 0x80 },
|
||||
}
|
||||
},
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7200I, ScanMethod::TRANSPARENCY, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7200I, ScanMethod::TRANSPARENCY_INFRARED, {
|
||||
{ 0xa8, 0x07, 0x07 },
|
||||
}, {
|
||||
{ 0xa8, 0x00, 0x07 },
|
||||
}
|
||||
},
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7300, ScanMethod::TRANSPARENCY, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7500I, ScanMethod::TRANSPARENCY, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7500I, ScanMethod::TRANSPARENCY_INFRARED, {
|
||||
{ 0xa8, 0x07, 0x07 },
|
||||
}, {
|
||||
{ 0xa8, 0x00, 0x07 },
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
for (const auto& setting : settings) {
|
||||
if (setting.model_id == dev.model->model_id &&
|
||||
setting.scan_method == dev.settings.scan_method)
|
||||
{
|
||||
apply_reg_settings_to_device(dev, set ? setting.regs_on : setting.regs_off);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw SaneException("Could not find XPA lamp settings");
|
||||
}
|
||||
|
||||
|
||||
void CommandSetCommon::set_motor_mode(Genesys_Device& dev, Genesys_Register_Set& regs,
|
||||
MotorMode mode) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
|
||||
struct MotorSettings {
|
||||
ModelId model_id;
|
||||
ResolutionFilter resolutions;
|
||||
GenesysRegisterSettingSet regs_primary_and_secondary;
|
||||
GenesysRegisterSettingSet regs_primary;
|
||||
GenesysRegisterSettingSet regs_secondary;
|
||||
};
|
||||
|
||||
MotorSettings settings[] = {
|
||||
{ ModelId::CANON_8400F, { 400, 800, 1600, 3200 }, {
|
||||
{ 0x6c, 0x00, 0x90 },
|
||||
{ 0xa9, 0x04, 0x06 },
|
||||
}, {
|
||||
{ 0x6c, 0x90, 0x90 },
|
||||
{ 0xa9, 0x02, 0x06 },
|
||||
}, {}
|
||||
},
|
||||
{ ModelId::CANON_8600F, { 300, 600, 1200 }, {
|
||||
{ 0x6c, 0x00, 0x60 },
|
||||
{ 0xa6, 0x01, 0x41 },
|
||||
}, {
|
||||
{ 0x6c, 0x20, 0x62 },
|
||||
{ 0xa6, 0x00, 0x41 },
|
||||
}, {
|
||||
{ 0x6c, 0x40, 0x62 },
|
||||
{ 0xa6, 0x01, 0x41 },
|
||||
}
|
||||
},
|
||||
{ ModelId::CANON_8600F, { 2400, 4800 }, {
|
||||
{ 0x6c, 0x02, 0x62 },
|
||||
{ 0xa6, 0x01, 0x41 },
|
||||
}, {
|
||||
{ 0x6c, 0x20, 0x62 },
|
||||
{ 0xa6, 0x00, 0x41 },
|
||||
}, {
|
||||
{ 0x6c, 0x40, 0x62 },
|
||||
{ 0xa6, 0x01, 0x41 },
|
||||
}
|
||||
},
|
||||
{ ModelId::HP_SCANJET_G4050, ResolutionFilter::ANY, {
|
||||
{ 0x6b, 0x81, 0x81 }, // set MULTFILM and GPOADF
|
||||
{ 0x6c, 0x00, 0x40 }, // note that reverse change is not applied on off
|
||||
// 0xa6 register 0x08 bit likely sets motor power. No move at all without that one
|
||||
{ 0xa6, 0x08, 0x08 }, // note that reverse change is not applied on off
|
||||
{ 0xa8, 0x00, 0x04 },
|
||||
{ 0xa9, 0x30, 0x30 },
|
||||
}, {
|
||||
{ 0x6b, 0x00, 0x01 }, // BUG: note that only ADF is unset
|
||||
{ 0xa8, 0x04, 0x04 },
|
||||
{ 0xa9, 0x00, 0x10 }, // note that 0x20 bit is not reset
|
||||
}, {}
|
||||
},
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7200I, ResolutionFilter::ANY, {}, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7300, ResolutionFilter::ANY, {}, {}, {} },
|
||||
{ ModelId::PLUSTEK_OPTICFILM_7500I, ResolutionFilter::ANY, {}, {}, {} },
|
||||
};
|
||||
|
||||
for (const auto& setting : settings) {
|
||||
if (setting.model_id == dev.model->model_id &&
|
||||
setting.resolutions.matches(dev.session.output_resolution))
|
||||
{
|
||||
switch (mode) {
|
||||
case MotorMode::PRIMARY: {
|
||||
apply_reg_settings_to_device(dev, setting.regs_primary);
|
||||
break;
|
||||
}
|
||||
case MotorMode::PRIMARY_AND_SECONDARY: {
|
||||
apply_reg_settings_to_device(dev, setting.regs_primary_and_secondary);
|
||||
break;
|
||||
}
|
||||
case MotorMode::SECONDARY: {
|
||||
apply_reg_settings_to_device(dev, setting.regs_secondary);
|
||||
break;
|
||||
}
|
||||
}
|
||||
regs.state.motor_mode = mode;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw SaneException("Motor settings have not been found");
|
||||
}
|
||||
|
||||
} // namespace genesys
|
|
@ -0,0 +1,48 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
|
||||
|
||||
This file is part of the SANE package.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef BACKEND_GENESYS_COMMAND_SET_COMMON_H
|
||||
#define BACKEND_GENESYS_COMMAND_SET_COMMON_H
|
||||
|
||||
#include "command_set.h"
|
||||
|
||||
namespace genesys {
|
||||
|
||||
|
||||
/** Common command set functionality
|
||||
*/
|
||||
class CommandSetCommon : public CommandSet
|
||||
{
|
||||
public:
|
||||
~CommandSetCommon() override;
|
||||
|
||||
bool is_head_home(Genesys_Device& dev, ScanHeadId scan_head) const override;
|
||||
|
||||
void set_xpa_lamp_power(Genesys_Device& dev, bool set) const override;
|
||||
|
||||
void set_motor_mode(Genesys_Device& dev, Genesys_Register_Set& regs,
|
||||
MotorMode mode) const override;
|
||||
};
|
||||
|
||||
} // namespace genesys
|
||||
|
||||
#endif // BACKEND_GENESYS_COMMAND_SET_COMMON_H
|
|
@ -62,15 +62,24 @@ std::vector<unsigned> MethodResolutions::get_resolutions() const
|
|||
return ret;
|
||||
}
|
||||
|
||||
const MethodResolutions& Genesys_Model::get_resolution_settings(ScanMethod method) const
|
||||
const MethodResolutions* Genesys_Model::get_resolution_settings_ptr(ScanMethod method) const
|
||||
{
|
||||
for (const auto& res_for_method : resolutions) {
|
||||
for (auto res_method : res_for_method.methods) {
|
||||
if (res_method == method) {
|
||||
return res_for_method;
|
||||
return &res_for_method;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
const MethodResolutions& Genesys_Model::get_resolution_settings(ScanMethod method) const
|
||||
{
|
||||
const auto* ptr = get_resolution_settings_ptr(method);
|
||||
if (ptr)
|
||||
return *ptr;
|
||||
|
||||
throw SaneException("Could not find resolution settings for method %d",
|
||||
static_cast<unsigned>(method));
|
||||
}
|
||||
|
@ -80,6 +89,12 @@ std::vector<unsigned> Genesys_Model::get_resolutions(ScanMethod method) const
|
|||
return get_resolution_settings(method).get_resolutions();
|
||||
}
|
||||
|
||||
bool Genesys_Model::has_method(ScanMethod method) const
|
||||
{
|
||||
return get_resolution_settings_ptr(method) != nullptr;
|
||||
}
|
||||
|
||||
|
||||
Genesys_Device::~Genesys_Device()
|
||||
{
|
||||
clear();
|
||||
|
@ -124,10 +139,14 @@ unsigned Genesys_Device::head_pos(ScanHeadId scan_head) const
|
|||
}
|
||||
}
|
||||
|
||||
void Genesys_Device::set_head_pos_unknown()
|
||||
void Genesys_Device::set_head_pos_unknown(ScanHeadId scan_head)
|
||||
{
|
||||
is_head_pos_primary_known_ = false;
|
||||
is_head_pos_secondary_known_ = false;
|
||||
if ((scan_head & ScanHeadId::PRIMARY) != ScanHeadId::NONE) {
|
||||
is_head_pos_primary_known_ = false;
|
||||
}
|
||||
if ((scan_head & ScanHeadId::SECONDARY) != ScanHeadId::NONE) {
|
||||
is_head_pos_secondary_known_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Genesys_Device::set_head_pos_zero(ScanHeadId scan_head)
|
||||
|
@ -205,11 +224,10 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev)
|
|||
<< " ignore_offsets: " << dev.ignore_offsets << '\n'
|
||||
<< " model: (not printed)\n"
|
||||
<< " reg: " << format_indent_braced_list(4, dev.reg) << '\n'
|
||||
<< " calib_reg: " << format_indent_braced_list(4, dev.calib_reg) << '\n'
|
||||
<< " initial_regs: " << format_indent_braced_list(4, dev.initial_regs) << '\n'
|
||||
<< " settings: " << format_indent_braced_list(4, dev.settings) << '\n'
|
||||
<< " frontend: " << format_indent_braced_list(4, dev.frontend) << '\n'
|
||||
<< " frontend_initial: " << format_indent_braced_list(4, dev.frontend_initial) << '\n'
|
||||
<< " frontend_is_init: " << dev.frontend_is_init << '\n'
|
||||
<< " gpo.regs: " << format_indent_braced_list(4, dev.gpo.regs) << '\n'
|
||||
<< " motor: " << format_indent_braced_list(4, dev.motor) << '\n'
|
||||
<< " control[0..6]: " << std::hex
|
||||
|
@ -220,13 +238,7 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev)
|
|||
<< static_cast<unsigned>(dev.control[4]) << ' '
|
||||
<< static_cast<unsigned>(dev.control[5]) << '\n' << std::dec
|
||||
<< " average_size: " << dev.average_size << '\n'
|
||||
<< " calib_pixels: " << dev.calib_pixels << '\n'
|
||||
<< " calib_lines: " << dev.calib_lines << '\n'
|
||||
<< " calib_channels: " << dev.calib_channels << '\n'
|
||||
<< " calib_resolution: " << dev.calib_resolution << '\n'
|
||||
<< " calib_total_bytes_to_read: " << dev.calib_total_bytes_to_read << '\n'
|
||||
<< " calib_session: " << format_indent_braced_list(4, dev.calib_session) << '\n'
|
||||
<< " calib_pixels_offset: " << dev.calib_pixels_offset << '\n'
|
||||
<< " gamma_override_tables[0].size(): " << dev.gamma_override_tables[0].size() << '\n'
|
||||
<< " gamma_override_tables[1].size(): " << dev.gamma_override_tables[1].size() << '\n'
|
||||
<< " gamma_override_tables[2].size(): " << dev.gamma_override_tables[2].size() << '\n'
|
||||
|
@ -262,11 +274,25 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev)
|
|||
|
||||
void apply_reg_settings_to_device(Genesys_Device& dev, const GenesysRegisterSettingSet& regs)
|
||||
{
|
||||
apply_reg_settings_to_device_with_backup(dev, regs);
|
||||
}
|
||||
|
||||
GenesysRegisterSettingSet
|
||||
apply_reg_settings_to_device_with_backup(Genesys_Device& dev,
|
||||
const GenesysRegisterSettingSet& regs)
|
||||
{
|
||||
GenesysRegisterSettingSet backup;
|
||||
for (const auto& reg : regs) {
|
||||
uint8_t val = dev.interface->read_register(reg.address);
|
||||
val = (val & ~reg.mask) | (reg.value & reg.mask);
|
||||
dev.interface->write_register(reg.address, val);
|
||||
std::uint8_t old_val = dev.interface->read_register(reg.address);
|
||||
std::uint8_t new_val = (old_val & ~reg.mask) | (reg.value & reg.mask);
|
||||
dev.interface->write_register(reg.address, new_val);
|
||||
|
||||
using SettingType = GenesysRegisterSettingSet::SettingType;
|
||||
backup.push_back(SettingType{reg.address,
|
||||
static_cast<std::uint8_t>(old_val & reg.mask),
|
||||
reg.mask});
|
||||
}
|
||||
return backup;
|
||||
}
|
||||
|
||||
} // namespace genesys
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "register.h"
|
||||
#include "usb_device.h"
|
||||
#include "scanner_interface.h"
|
||||
#include "utilities.h"
|
||||
#include <vector>
|
||||
|
||||
namespace genesys {
|
||||
|
@ -77,24 +78,6 @@ struct Genesys_Gpo
|
|||
GenesysRegisterSettingSet regs;
|
||||
};
|
||||
|
||||
/// Stores a SANE_Fixed value which is automatically converted from and to floating-point values
|
||||
class FixedFloat
|
||||
{
|
||||
public:
|
||||
FixedFloat() = default;
|
||||
FixedFloat(const FixedFloat&) = default;
|
||||
FixedFloat(double number) : value_{SANE_FIX(number)} {}
|
||||
FixedFloat& operator=(const FixedFloat&) = default;
|
||||
FixedFloat& operator=(double number) { value_ = SANE_FIX(number); return *this; }
|
||||
|
||||
operator double() const { return value(); }
|
||||
|
||||
double value() const { return SANE_UNFIX(value_); }
|
||||
|
||||
private:
|
||||
SANE_Fixed value_ = 0;
|
||||
};
|
||||
|
||||
struct MethodResolutions
|
||||
{
|
||||
std::vector<ScanMethod> methods;
|
||||
|
@ -143,49 +126,65 @@ struct Genesys_Model
|
|||
// All offsets below are with respect to the sensor home position
|
||||
|
||||
// Start of scan area in mm
|
||||
FixedFloat x_offset = 0;
|
||||
float x_offset = 0;
|
||||
|
||||
// Start of scan area in mm (Amount of feeding needed to get to the medium)
|
||||
FixedFloat y_offset = 0;
|
||||
float y_offset = 0;
|
||||
|
||||
// Size of scan area in mm
|
||||
FixedFloat x_size = 0;
|
||||
float x_size = 0;
|
||||
|
||||
// Size of scan area in mm
|
||||
FixedFloat y_size = 0;
|
||||
float y_size = 0;
|
||||
|
||||
// Start of white strip in mm
|
||||
FixedFloat y_offset_calib_white = 0;
|
||||
// Start of white strip in mm for scanners that use separate dark and white shading calibration.
|
||||
float y_offset_calib_white = 0;
|
||||
|
||||
// The size of the scan area that is used to acquire shading data in mm
|
||||
float y_size_calib_mm = 0;
|
||||
|
||||
// Start of the black/white strip in mm for scanners that use unified dark and white shading
|
||||
// calibration.
|
||||
float y_offset_calib_dark_white_mm = 0;
|
||||
|
||||
// The size of the scan area that is used to acquire dark/white shading data in mm
|
||||
float y_size_calib_dark_white_mm = 0;
|
||||
|
||||
// The width of the scan area that is used to acquire shading data
|
||||
float x_size_calib_mm = 0;
|
||||
|
||||
// Start of black mark in mm
|
||||
FixedFloat x_offset_calib_black = 0;
|
||||
float x_offset_calib_black = 0;
|
||||
|
||||
// Start of scan area in transparency mode in mm
|
||||
FixedFloat x_offset_ta = 0;
|
||||
float x_offset_ta = 0;
|
||||
|
||||
// Start of scan area in transparency mode in mm
|
||||
FixedFloat y_offset_ta = 0;
|
||||
float y_offset_ta = 0;
|
||||
|
||||
// Size of scan area in transparency mode in mm
|
||||
FixedFloat x_size_ta = 0;
|
||||
float x_size_ta = 0;
|
||||
|
||||
// Size of scan area in transparency mode in mm
|
||||
FixedFloat y_size_ta = 0;
|
||||
float y_size_ta = 0;
|
||||
|
||||
// The position of the sensor when it's aligned with the lamp for transparency scanning
|
||||
FixedFloat y_offset_sensor_to_ta = 0;
|
||||
float y_offset_sensor_to_ta = 0;
|
||||
|
||||
// Start of white strip in transparency mode in mm
|
||||
FixedFloat y_offset_calib_white_ta = 0;
|
||||
float y_offset_calib_white_ta = 0;
|
||||
|
||||
// Start of black strip in transparency mode in mm
|
||||
FixedFloat y_offset_calib_black_ta = 0;
|
||||
float y_offset_calib_black_ta = 0;
|
||||
|
||||
// The size of the scan area that is used to acquire shading data in transparency mode in mm
|
||||
float y_size_calib_ta_mm = 0;
|
||||
|
||||
// Size of scan area after paper sensor stop sensing document in mm
|
||||
FixedFloat post_scan = 0;
|
||||
float post_scan = 0;
|
||||
|
||||
// Amount of feeding needed to eject document after finishing scanning in mm
|
||||
FixedFloat eject_feed = 0;
|
||||
float eject_feed = 0;
|
||||
|
||||
// Line-distance correction (in pixel at optical_ydpi) for CCD scanners
|
||||
SANE_Int ld_shift_r = 0;
|
||||
|
@ -210,22 +209,24 @@ struct Genesys_Model
|
|||
// stepper motor type
|
||||
MotorId motor_id = MotorId::UNKNOWN;
|
||||
|
||||
// Which hacks are needed for this scanner?
|
||||
SANE_Word flags = 0;
|
||||
// Which customizations are needed for this scanner?
|
||||
ModelFlag flags = ModelFlag::NONE;
|
||||
|
||||
// Button flags, described existing buttons for the model
|
||||
SANE_Word buttons = 0;
|
||||
|
||||
// how many lines are used for shading calibration
|
||||
SANE_Int shading_lines = 0;
|
||||
// how many lines are used for shading calibration in TA mode
|
||||
SANE_Int shading_ta_lines = 0;
|
||||
// how many lines are used to search start position
|
||||
SANE_Int search_lines = 0;
|
||||
|
||||
// returns nullptr if method is not supported
|
||||
const MethodResolutions* get_resolution_settings_ptr(ScanMethod method) const;
|
||||
|
||||
// throws if method is not supported
|
||||
const MethodResolutions& get_resolution_settings(ScanMethod method) const;
|
||||
|
||||
std::vector<unsigned> get_resolutions(ScanMethod method) const;
|
||||
|
||||
bool has_method(ScanMethod method) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -267,36 +268,18 @@ struct Genesys_Device
|
|||
std::unique_ptr<CommandSet> cmd_set;
|
||||
|
||||
Genesys_Register_Set reg;
|
||||
Genesys_Register_Set calib_reg;
|
||||
Genesys_Register_Set initial_regs;
|
||||
Genesys_Settings settings;
|
||||
Genesys_Frontend frontend, frontend_initial;
|
||||
|
||||
// whether the frontend is initialized. This is currently used just to preserve historical
|
||||
// behavior
|
||||
bool frontend_is_init = false;
|
||||
|
||||
Genesys_Gpo gpo;
|
||||
Genesys_Motor motor;
|
||||
std::uint8_t control[6] = {};
|
||||
|
||||
size_t average_size = 0;
|
||||
// number of pixels used during shading calibration
|
||||
size_t calib_pixels = 0;
|
||||
// number of lines used during shading calibration
|
||||
size_t calib_lines = 0;
|
||||
size_t calib_channels = 0;
|
||||
size_t calib_resolution = 0;
|
||||
// bytes to read from USB when calibrating. If 0, this is not set
|
||||
size_t calib_total_bytes_to_read = 0;
|
||||
|
||||
// the session that was configured for calibration
|
||||
ScanSession calib_session;
|
||||
|
||||
// certain scanners support much higher resolution when scanning transparency, but we can't
|
||||
// read whole width of the scanner as a single line at that resolution. Thus for stuff like
|
||||
// calibration we want to read only the possible calibration area.
|
||||
size_t calib_pixels_offset = 0;
|
||||
|
||||
// gamma overrides. If a respective array is not empty then it means that the gamma for that
|
||||
// color is overridden.
|
||||
std::vector<std::uint16_t> gamma_override_tables[3];
|
||||
|
@ -360,7 +343,7 @@ struct Genesys_Device
|
|||
|
||||
bool is_head_pos_known(ScanHeadId scan_head) const;
|
||||
unsigned head_pos(ScanHeadId scan_head) const;
|
||||
void set_head_pos_unknown();
|
||||
void set_head_pos_unknown(ScanHeadId scan_head);
|
||||
void set_head_pos_zero(ScanHeadId scan_head);
|
||||
void advance_head_pos_by_session(ScanHeadId scan_head);
|
||||
void advance_head_pos_by_steps(ScanHeadId scan_head, Direction direction, unsigned steps);
|
||||
|
@ -382,6 +365,10 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev);
|
|||
|
||||
void apply_reg_settings_to_device(Genesys_Device& dev, const GenesysRegisterSettingSet& regs);
|
||||
|
||||
GenesysRegisterSettingSet
|
||||
apply_reg_settings_to_device_with_backup(Genesys_Device& dev,
|
||||
const GenesysRegisterSettingSet& regs);
|
||||
|
||||
} // namespace genesys
|
||||
|
||||
#endif
|
||||
|
|
|
@ -192,7 +192,7 @@ enum class ModelId : unsigned
|
|||
DCT_DOCKETPORT_487,
|
||||
HP_SCANJET_2300C,
|
||||
HP_SCANJET_2400C,
|
||||
HP_SCANJET_3670C,
|
||||
HP_SCANJET_3670,
|
||||
HP_SCANJET_4850C,
|
||||
HP_SCANJET_G4010,
|
||||
HP_SCANJET_G4050,
|
||||
|
@ -431,6 +431,76 @@ enum class AsicType : unsigned
|
|||
};
|
||||
|
||||
|
||||
enum class ModelFlag : unsigned
|
||||
{
|
||||
// no flags
|
||||
NONE = 0,
|
||||
|
||||
// scanner is not tested, print a warning as it's likely it won't work
|
||||
UNTESTED = 1 << 0,
|
||||
|
||||
// use 14-bit gamma table instead of 12-bit
|
||||
GAMMA_14BIT = 1 << 1,
|
||||
|
||||
// skip lamp warmup (genesys_warmup())
|
||||
SKIP_WARMUP = 1 << 4,
|
||||
|
||||
// repark head and check for lock by moving without scanning
|
||||
REPARK = 1 << 7,
|
||||
|
||||
// do dark calibration
|
||||
DARK_CALIBRATION = 1 << 8,
|
||||
|
||||
// whether scanner must wait for the head while parking
|
||||
MUST_WAIT = 1 << 10,
|
||||
|
||||
// do dark and white calibration in one run
|
||||
DARK_WHITE_CALIBRATION = 1 << 12,
|
||||
|
||||
// allow custom gamma tables
|
||||
CUSTOM_GAMMA = 1 << 13,
|
||||
|
||||
// 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 16-bit data that is byte-inverted
|
||||
INVERTED_16BIT_DATA = 1 << 20,
|
||||
|
||||
// the scanner has transparency, but it's implemented using only one motor
|
||||
UTA_NO_SECONDARY_MOTOR = 1 << 21
|
||||
};
|
||||
|
||||
inline ModelFlag operator|(ModelFlag left, ModelFlag right)
|
||||
{
|
||||
return static_cast<ModelFlag>(static_cast<unsigned>(left) | static_cast<unsigned>(right));
|
||||
}
|
||||
|
||||
inline ModelFlag& operator|=(ModelFlag& left, ModelFlag right)
|
||||
{
|
||||
left = left | right;
|
||||
return left;
|
||||
}
|
||||
|
||||
inline ModelFlag operator&(ModelFlag left, ModelFlag right)
|
||||
{
|
||||
return static_cast<ModelFlag>(static_cast<unsigned>(left) & static_cast<unsigned>(right));
|
||||
}
|
||||
|
||||
inline bool has_flag(ModelFlag flags, ModelFlag which)
|
||||
{
|
||||
return (flags & which) == which;
|
||||
}
|
||||
|
||||
|
||||
enum class ScanFlag : unsigned
|
||||
{
|
||||
NONE = 0,
|
||||
|
@ -438,14 +508,22 @@ enum class ScanFlag : unsigned
|
|||
DISABLE_SHADING = 1 << 1,
|
||||
DISABLE_GAMMA = 1 << 2,
|
||||
DISABLE_BUFFER_FULL_MOVE = 1 << 3,
|
||||
IGNORE_LINE_DISTANCE = 1 << 4,
|
||||
DISABLE_LAMP = 1 << 5,
|
||||
CALIBRATION = 1 << 6,
|
||||
FEEDING = 1 << 7,
|
||||
USE_XPA = 1 << 8,
|
||||
ENABLE_LEDADD = 1 << 9,
|
||||
USE_XCORRECTION = 1 << 10,
|
||||
REVERSE = 1 << 11,
|
||||
|
||||
// if this flag is set the sensor will always be handled ignoring staggering of multiple
|
||||
// sensors to achieve high resolution.
|
||||
IGNORE_STAGGER_OFFSET = 1 << 4,
|
||||
|
||||
// if this flag is set the sensor will always be handled as if the components that scan
|
||||
// different colors are at the same position.
|
||||
IGNORE_COLOR_OFFSET = 1 << 5,
|
||||
|
||||
DISABLE_LAMP = 1 << 6,
|
||||
CALIBRATION = 1 << 7,
|
||||
FEEDING = 1 << 8,
|
||||
USE_XPA = 1 << 9,
|
||||
ENABLE_LEDADD = 1 << 10,
|
||||
USE_XCORRECTION = 1 << 11,
|
||||
REVERSE = 1 << 12,
|
||||
};
|
||||
|
||||
inline ScanFlag operator|(ScanFlag left, ScanFlag right)
|
||||
|
@ -524,6 +602,12 @@ enum class Direction : unsigned
|
|||
BACKWARD = 1
|
||||
};
|
||||
|
||||
enum class MotorMode : unsigned
|
||||
{
|
||||
PRIMARY = 0,
|
||||
PRIMARY_AND_SECONDARY,
|
||||
SECONDARY,
|
||||
};
|
||||
|
||||
} // namespace genesys
|
||||
|
||||
|
|
|
@ -56,7 +56,6 @@ struct Genesys_Calibration_Cache;
|
|||
class CommandSet;
|
||||
|
||||
// device.h
|
||||
class FixedFloat;
|
||||
struct Genesys_Gpo;
|
||||
struct MethodResolutions;
|
||||
struct Genesys_Model;
|
||||
|
@ -75,7 +74,6 @@ class Image;
|
|||
|
||||
// image_buffer.h
|
||||
class ImageBuffer;
|
||||
class FakeBufferModel;
|
||||
class ImageBufferGenesysUsb;
|
||||
|
||||
// image_pipeline.h
|
||||
|
@ -89,11 +87,11 @@ struct RawPixel;
|
|||
|
||||
// low.h
|
||||
struct Genesys_USB_Device_Entry;
|
||||
struct Motor_Profile;
|
||||
|
||||
// motor.h
|
||||
struct Genesys_Motor;
|
||||
struct MotorSlope;
|
||||
struct MotorProfile;
|
||||
struct MotorSlopeTable;
|
||||
|
||||
// register.h
|
||||
|
@ -113,6 +111,7 @@ class ScannerInterfaceUsb;
|
|||
class TestScannerInterface;
|
||||
|
||||
// sensor.h
|
||||
class ScanMethodFilter;
|
||||
class ResolutionFilter;
|
||||
struct GenesysFrontendLayout;
|
||||
struct Genesys_Frontend;
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -337,8 +337,6 @@ gl124_init_registers (Genesys_Device * dev)
|
|||
// fine tune upon device description
|
||||
const auto& sensor = sanei_genesys_find_sensor_any(dev);
|
||||
sanei_genesys_set_dpihw(dev->reg, sensor, sensor.optical_res);
|
||||
|
||||
dev->calib_reg = dev->reg;
|
||||
}
|
||||
|
||||
/**@brief send slope table for motor movement
|
||||
|
@ -466,7 +464,7 @@ void CommandSetGl124::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
|||
static void gl124_init_motor_regs_scan(Genesys_Device* dev,
|
||||
const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg,
|
||||
const Motor_Profile& motor_profile,
|
||||
const MotorProfile& motor_profile,
|
||||
unsigned int scan_exposure_time,
|
||||
unsigned scan_yres,
|
||||
unsigned int scan_lines,
|
||||
|
@ -711,7 +709,7 @@ static void gl124_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
|
|||
regs_set_optical_off(dev->model->asic_type, *reg);
|
||||
r = sanei_genesys_get_address (reg, REG_0x01);
|
||||
if (has_flag(session.params.flags, ScanFlag::DISABLE_SHADING) ||
|
||||
(dev->model->flags & GENESYS_FLAG_NO_CALIBRATION))
|
||||
has_flag(dev->model->flags, ModelFlag::NO_CALIBRATION))
|
||||
{
|
||||
r->value &= ~REG_0x01_DVDSET;
|
||||
} else {
|
||||
|
@ -818,7 +816,7 @@ static void gl124_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
|
|||
|
||||
dev->line_count = 0;
|
||||
|
||||
build_image_pipeline(dev, session);
|
||||
build_image_pipeline(dev, sensor, session);
|
||||
|
||||
// MAXWD is expressed in 2 words unit
|
||||
|
||||
|
@ -856,9 +854,7 @@ void CommandSetGl124::init_regs_for_scan_session(Genesys_Device* dev, const Gene
|
|||
} else {
|
||||
exposure_time = sensor.exposure_lperiod;
|
||||
}
|
||||
const auto& motor_profile = sanei_genesys_get_motor_profile(*gl124_motor_profiles,
|
||||
dev->model->motor_id,
|
||||
exposure_time);
|
||||
const auto& motor_profile = get_motor_profile(dev->motor.profiles, exposure_time, session);
|
||||
|
||||
DBG(DBG_info, "%s : exposure_time=%d pixels\n", __func__, exposure_time);
|
||||
DBG(DBG_info, "%s : scan_step_type=%d\n", __func__, static_cast<unsigned>(motor_profile.step_type));
|
||||
|
@ -885,8 +881,7 @@ void CommandSetGl124::init_regs_for_scan_session(Genesys_Device* dev, const Gene
|
|||
mflags |= MotorFlag::REVERSE;
|
||||
}
|
||||
gl124_init_motor_regs_scan(dev, sensor, reg, motor_profile, exposure_time, slope_dpi,
|
||||
dev->model->is_cis ? session.output_line_count * session.params.channels :
|
||||
session.output_line_count,
|
||||
session.optical_line_count,
|
||||
dummy, move, session.params.scan_mode, mflags);
|
||||
|
||||
/*** prepares data reordering ***/
|
||||
|
@ -909,21 +904,24 @@ ScanSession CommandSetGl124::calculate_scan_session(const Genesys_Device* dev,
|
|||
const Genesys_Sensor& sensor,
|
||||
const Genesys_Settings& settings) const
|
||||
{
|
||||
int start;
|
||||
|
||||
DBG(DBG_info, "%s ", __func__);
|
||||
debug_dump(DBG_info, settings);
|
||||
|
||||
/* start */
|
||||
start = static_cast<int>(dev->model->x_offset);
|
||||
start += static_cast<int>(settings.tl_x);
|
||||
start = static_cast<int>((start * sensor.optical_res) / MM_PER_INCH);
|
||||
unsigned move_dpi = dev->motor.base_ydpi / 4;
|
||||
float move = dev->model->y_offset;
|
||||
move += dev->settings.tl_y;
|
||||
move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
|
||||
|
||||
float start = dev->model->x_offset;
|
||||
start += settings.tl_x;
|
||||
start /= sensor.get_ccd_size_divisor_for_dpi(settings.xres);
|
||||
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 = start;
|
||||
session.params.starty = 0; // not used
|
||||
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;
|
||||
|
@ -1031,8 +1029,7 @@ void CommandSetGl124::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sens
|
|||
// set up GPIO for scan
|
||||
gl124_setup_scan_gpio(dev,dev->settings.yres);
|
||||
|
||||
// clear scan and feed count
|
||||
dev->interface->write_register(REG_0x0D, REG_0x0D_CLRLNCNT | REG_0x0D_CLRMCNT);
|
||||
scanner_clear_scan_and_feed_counts(*dev);
|
||||
|
||||
// enable scan and motor
|
||||
uint8_t val = dev->interface->read_register(REG_0x01);
|
||||
|
@ -1069,155 +1066,27 @@ void CommandSetGl124::move_back_home(Genesys_Device* dev, bool wait_until_home)
|
|||
scanner_move_back_home(*dev, wait_until_home);
|
||||
}
|
||||
|
||||
// Automatically set top-left edge of the scan area by scanning a 200x200 pixels area at 600 dpi
|
||||
// from very top of scanner
|
||||
void CommandSetGl124::search_start_position(Genesys_Device* dev) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
int size;
|
||||
Genesys_Register_Set local_reg = dev->reg;
|
||||
|
||||
int pixels = 600;
|
||||
int dpi = 300;
|
||||
|
||||
/* sets for a 200 lines * 600 pixels */
|
||||
/* normal scan with no shading */
|
||||
|
||||
// FIXME: the current approach of doing search only for one resolution does not work on scanners
|
||||
// whith employ different sensors with potentially different settings.
|
||||
const auto& sensor = sanei_genesys_find_sensor(dev, dpi, 1, ScanMethod::FLATBED);
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = dpi;
|
||||
session.params.yres = dpi;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = 0; /*we should give a small offset here~60 steps */
|
||||
session.params.pixels = 600;
|
||||
session.params.lines = dev->model->search_lines;
|
||||
session.params.depth = 8;
|
||||
session.params.channels = 1;
|
||||
session.params.scan_method = dev->settings.scan_method;
|
||||
session.params.scan_mode = ScanColorMode::GRAY;
|
||||
session.params.color_filter = ColorFilter::GREEN;
|
||||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE |
|
||||
ScanFlag::DISABLE_BUFFER_FULL_MOVE;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, sensor, &local_reg, session);
|
||||
|
||||
// send to scanner
|
||||
dev->interface->write_registers(local_reg);
|
||||
|
||||
size = pixels * dev->model->search_lines;
|
||||
|
||||
std::vector<uint8_t> data(size);
|
||||
|
||||
begin_scan(dev, sensor, &local_reg, true);
|
||||
|
||||
if (is_testing_mode()) {
|
||||
dev->interface->test_checkpoint("search_start_position");
|
||||
end_scan(dev, &local_reg, true);
|
||||
dev->reg = local_reg;
|
||||
return;
|
||||
}
|
||||
|
||||
wait_until_buffer_non_empty(dev);
|
||||
|
||||
// now we're on target, we can read data
|
||||
sanei_genesys_read_data_from_scanner(dev, data.data(), size);
|
||||
|
||||
if (DBG_LEVEL >= DBG_data) {
|
||||
sanei_genesys_write_pnm_file("gl124_search_position.pnm", data.data(), 8, 1, pixels,
|
||||
dev->model->search_lines);
|
||||
}
|
||||
|
||||
end_scan(dev, &local_reg, true);
|
||||
|
||||
/* update regs to copy ASIC internal state */
|
||||
dev->reg = local_reg;
|
||||
|
||||
for (auto& sensor_update :
|
||||
sanei_genesys_find_sensors_all_for_write(dev, dev->model->default_method))
|
||||
{
|
||||
sanei_genesys_search_reference_point(dev, sensor_update, data.data(), 0, dpi, pixels,
|
||||
dev->model->search_lines);
|
||||
}
|
||||
}
|
||||
|
||||
// sets up register for coarse gain calibration
|
||||
// todo: check it for scanners using it
|
||||
void CommandSetGl124::init_regs_for_coarse_calibration(Genesys_Device* dev,
|
||||
const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = dev->settings.xres;
|
||||
session.params.yres = dev->settings.yres;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = 0;
|
||||
session.params.pixels = sensor.optical_res / sensor.ccd_pixels_per_system_pixel();
|
||||
session.params.lines = 20;
|
||||
session.params.depth = 16;
|
||||
session.params.channels = dev->settings.get_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 = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::SINGLE_LINE |
|
||||
ScanFlag::FEEDING |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, sensor, ®s, session);
|
||||
|
||||
sanei_genesys_set_motor_power(regs, false);
|
||||
|
||||
DBG(DBG_info, "%s: optical sensor res: %d dpi, actual res: %d\n", __func__,
|
||||
sensor.optical_res / sensor.ccd_pixels_per_system_pixel(), dev->settings.xres);
|
||||
|
||||
dev->interface->write_registers(regs);
|
||||
}
|
||||
|
||||
|
||||
// init registers for shading calibration shading calibration is done at dpihw
|
||||
void CommandSetGl124::init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
int move, resolution, dpihw, factor;
|
||||
|
||||
/* initial calibration reg values */
|
||||
regs = dev->reg;
|
||||
|
||||
dev->calib_channels = 3;
|
||||
dev->calib_lines = dev->model->shading_lines;
|
||||
dpihw = sensor.get_register_hwdpi(dev->settings.xres);
|
||||
if(dpihw>=2400)
|
||||
{
|
||||
dev->calib_lines *= 2;
|
||||
}
|
||||
resolution=dpihw;
|
||||
unsigned channels = 3;
|
||||
unsigned dpihw = sensor.get_register_hwdpi(dev->settings.xres);
|
||||
unsigned resolution = dpihw;
|
||||
|
||||
unsigned ccd_size_divisor = sensor.get_ccd_size_divisor_for_dpi(dev->settings.xres);
|
||||
|
||||
resolution /= ccd_size_divisor;
|
||||
dev->calib_lines /= ccd_size_divisor; // reducing just because we reduced the resolution
|
||||
unsigned calib_lines =
|
||||
static_cast<unsigned>(dev->model->y_size_calib_mm * resolution / MM_PER_INCH);
|
||||
|
||||
const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution,
|
||||
dev->calib_channels,
|
||||
const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
|
||||
dev->settings.scan_method);
|
||||
dev->calib_resolution = resolution;
|
||||
dev->calib_total_bytes_to_read = 0;
|
||||
factor = calib_sensor.optical_res / resolution;
|
||||
dev->calib_pixels = calib_sensor.sensor_pixels / factor;
|
||||
|
||||
/* distance to move to reach white target at high resolution */
|
||||
move=0;
|
||||
unsigned move=0;
|
||||
if (dev->settings.yres >= 1200) {
|
||||
move = static_cast<int>(dev->model->y_offset_calib_white);
|
||||
move = static_cast<int>((move * (dev->motor.base_ydpi/4)) / MM_PER_INCH);
|
||||
|
@ -1229,17 +1098,16 @@ void CommandSetGl124::init_regs_for_shading(Genesys_Device* dev, const Genesys_S
|
|||
session.params.yres = resolution;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = move;
|
||||
session.params.pixels = dev->calib_pixels;
|
||||
session.params.lines = dev->calib_lines;
|
||||
session.params.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
|
||||
session.params.lines = calib_lines;
|
||||
session.params.depth = 16;
|
||||
session.params.channels = dev->calib_channels;
|
||||
session.params.channels = channels;
|
||||
session.params.scan_method = dev->settings.scan_method;
|
||||
session.params.scan_mode = ScanColorMode::COLOR_SINGLE_PASS;
|
||||
session.params.color_filter = ColorFilter::RED;
|
||||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::DISABLE_BUFFER_FULL_MOVE |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
ScanFlag::DISABLE_BUFFER_FULL_MOVE;
|
||||
compute_session(dev, session, calib_sensor);
|
||||
|
||||
try {
|
||||
|
@ -1250,7 +1118,7 @@ void CommandSetGl124::init_regs_for_shading(Genesys_Device* dev, const Genesys_S
|
|||
}
|
||||
sanei_genesys_set_motor_power(regs, false);
|
||||
|
||||
dev->interface->write_registers(regs);
|
||||
dev->calib_session = session;
|
||||
}
|
||||
|
||||
void CommandSetGl124::wait_for_motor_stop(Genesys_Device* dev) const
|
||||
|
@ -1274,52 +1142,21 @@ void CommandSetGl124::wait_for_motor_stop(Genesys_Device* dev) const
|
|||
|
||||
/** @brief set up registers for the actual scan
|
||||
*/
|
||||
void CommandSetGl124::init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const
|
||||
void CommandSetGl124::init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
float move;
|
||||
int move_dpi;
|
||||
float start;
|
||||
auto session = calculate_scan_session(dev, sensor, dev->settings);
|
||||
|
||||
debug_dump(DBG_info, dev->settings);
|
||||
|
||||
/* y (motor) distance to move to reach scanned area */
|
||||
move_dpi = dev->motor.base_ydpi/4;
|
||||
move = static_cast<float>(dev->model->y_offset);
|
||||
move += static_cast<float>(dev->settings.tl_y);
|
||||
move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
|
||||
DBG (DBG_info, "%s: move=%f steps\n", __func__, move);
|
||||
|
||||
if (dev->settings.get_channels() * dev->settings.yres >= 600 && move > 700) {
|
||||
scanner_move(*dev, dev->model->default_method, static_cast<unsigned>(move - 500),
|
||||
if (dev->settings.get_channels() * dev->settings.yres >= 600 && session.params.starty > 700) {
|
||||
scanner_move(*dev, dev->model->default_method,
|
||||
static_cast<unsigned>(session.params.starty - 500),
|
||||
Direction::FORWARD);
|
||||
move=500;
|
||||
session.params.starty = 500;
|
||||
}
|
||||
DBG(DBG_info, "%s: move=%f steps\n", __func__, move);
|
||||
|
||||
/* start */
|
||||
start = static_cast<float>(dev->model->x_offset);
|
||||
start += static_cast<float>(dev->settings.tl_x);
|
||||
start /= sensor.get_ccd_size_divisor_for_dpi(dev->settings.xres);
|
||||
start = static_cast<float>((start * sensor.optical_res) / MM_PER_INCH);
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = dev->settings.xres;
|
||||
session.params.yres = dev->settings.yres;
|
||||
session.params.startx = static_cast<unsigned>(start);
|
||||
session.params.starty = static_cast<unsigned>(move);
|
||||
session.params.pixels = dev->settings.pixels;
|
||||
session.params.requested_pixels = dev->settings.requested_pixels;
|
||||
session.params.lines = dev->settings.lines;
|
||||
session.params.depth = dev->settings.depth;
|
||||
session.params.channels = dev->settings.get_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 = ScanFlag::NONE;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, sensor, &dev->reg, session);
|
||||
init_regs_for_scan_session(dev, sensor, ®s, session);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1439,14 +1276,11 @@ static void move_to_calibration_area(Genesys_Device* dev, const Genesys_Sensor&
|
|||
(void) sensor;
|
||||
|
||||
DBG_HELPER(dbg);
|
||||
int pixels;
|
||||
int size;
|
||||
|
||||
unsigned resolution = 600;
|
||||
unsigned channels = 3;
|
||||
const auto& move_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
|
||||
dev->settings.scan_method);
|
||||
pixels = (move_sensor.sensor_pixels * 600) / move_sensor.optical_res;
|
||||
|
||||
/* initial calibration reg values */
|
||||
regs = dev->reg;
|
||||
|
@ -1456,7 +1290,7 @@ static void move_to_calibration_area(Genesys_Device* dev, const Genesys_Sensor&
|
|||
session.params.yres = resolution;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = 0;
|
||||
session.params.pixels = pixels;
|
||||
session.params.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
|
||||
session.params.lines = 1;
|
||||
session.params.depth = 8;
|
||||
session.params.channels = channels;
|
||||
|
@ -1466,14 +1300,12 @@ static void move_to_calibration_area(Genesys_Device* dev, const Genesys_Sensor&
|
|||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::SINGLE_LINE |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
ScanFlag::IGNORE_STAGGER_OFFSET |
|
||||
ScanFlag::IGNORE_COLOR_OFFSET;
|
||||
compute_session(dev, session, move_sensor);
|
||||
|
||||
dev->cmd_set->init_regs_for_scan_session(dev, move_sensor, ®s, session);
|
||||
|
||||
size = pixels * 3;
|
||||
std::vector<uint8_t> line(size);
|
||||
|
||||
// write registers and scan data
|
||||
dev->interface->write_registers(regs);
|
||||
|
||||
|
@ -1486,14 +1318,13 @@ static void move_to_calibration_area(Genesys_Device* dev, const Genesys_Sensor&
|
|||
return;
|
||||
}
|
||||
|
||||
sanei_genesys_read_data_from_scanner(dev, line.data(), size);
|
||||
auto image = read_unshuffled_image_from_scanner(dev, session, session.output_line_bytes);
|
||||
|
||||
// stop scanning
|
||||
scanner_stop_action(*dev);
|
||||
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
sanei_genesys_write_pnm_file("gl124_movetocalarea.pnm", line.data(), 8, 3, pixels, 1);
|
||||
if (DBG_LEVEL >= DBG_data) {
|
||||
sanei_genesys_write_pnm_file("gl124_movetocalarea.pnm", image);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1506,13 +1337,9 @@ SensorExposure CommandSetGl124::led_calibration(Genesys_Device* dev, const Genes
|
|||
Genesys_Register_Set& regs) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
int num_pixels;
|
||||
int total_size;
|
||||
int resolution;
|
||||
int dpihw;
|
||||
int i, j;
|
||||
int val;
|
||||
int channels;
|
||||
int i;
|
||||
int avg[3];
|
||||
int turn;
|
||||
uint16_t exp[3],target;
|
||||
|
@ -1521,7 +1348,7 @@ SensorExposure CommandSetGl124::led_calibration(Genesys_Device* dev, const Genes
|
|||
move_to_calibration_area(dev, sensor, regs);
|
||||
|
||||
/* offset calibration is always done in 16 bit depth color mode */
|
||||
channels = 3;
|
||||
unsigned channels = 3;
|
||||
dpihw = sensor.get_register_hwdpi(dev->settings.xres);
|
||||
resolution = dpihw;
|
||||
unsigned ccd_size_divisor = sensor.get_ccd_size_divisor_for_dpi(dev->settings.xres);
|
||||
|
@ -1529,7 +1356,6 @@ SensorExposure CommandSetGl124::led_calibration(Genesys_Device* dev, const Genes
|
|||
|
||||
const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
|
||||
dev->settings.scan_method);
|
||||
num_pixels = (calib_sensor.sensor_pixels * resolution) / calib_sensor.optical_res;
|
||||
|
||||
/* initial calibration reg values */
|
||||
regs = dev->reg;
|
||||
|
@ -1539,7 +1365,7 @@ SensorExposure CommandSetGl124::led_calibration(Genesys_Device* dev, const Genes
|
|||
session.params.yres = resolution;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = 0;
|
||||
session.params.pixels = num_pixels;
|
||||
session.params.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;;
|
||||
session.params.lines = 1;
|
||||
session.params.depth = 16;
|
||||
session.params.channels = channels;
|
||||
|
@ -1549,14 +1375,12 @@ SensorExposure CommandSetGl124::led_calibration(Genesys_Device* dev, const Genes
|
|||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::SINGLE_LINE |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
ScanFlag::IGNORE_STAGGER_OFFSET |
|
||||
ScanFlag::IGNORE_COLOR_OFFSET;
|
||||
compute_session(dev, session, calib_sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, calib_sensor, ®s, session);
|
||||
|
||||
total_size = num_pixels * channels * (session.params.depth / 8) * 1;
|
||||
std::vector<uint8_t> line(total_size);
|
||||
|
||||
// initial loop values and boundaries
|
||||
exp[0] = calib_sensor.exposure.red;
|
||||
exp[1] = calib_sensor.exposure.green;
|
||||
|
@ -1587,7 +1411,7 @@ SensorExposure CommandSetGl124::led_calibration(Genesys_Device* dev, const Genes
|
|||
return calib_sensor.exposure;
|
||||
}
|
||||
|
||||
sanei_genesys_read_data_from_scanner(dev, line.data(), total_size);
|
||||
auto image = read_unshuffled_image_from_scanner(dev, session, session.output_line_bytes);
|
||||
|
||||
// stop scanning
|
||||
scanner_stop_action(*dev);
|
||||
|
@ -1596,29 +1420,16 @@ SensorExposure CommandSetGl124::led_calibration(Genesys_Device* dev, const Genes
|
|||
{
|
||||
char fn[30];
|
||||
std::snprintf(fn, 30, "gl124_led_%02d.pnm", turn);
|
||||
sanei_genesys_write_pnm_file(fn, line.data(), session.params.depth, channels, num_pixels,
|
||||
1);
|
||||
}
|
||||
sanei_genesys_write_pnm_file(fn, image);
|
||||
}
|
||||
|
||||
/* compute average */
|
||||
for (j = 0; j < channels; j++)
|
||||
{
|
||||
avg[j] = 0;
|
||||
for (i = 0; i < num_pixels; i++)
|
||||
{
|
||||
if (dev->model->is_cis)
|
||||
val =
|
||||
line[i * 2 + j * 2 * num_pixels + 1] * 256 +
|
||||
line[i * 2 + j * 2 * num_pixels];
|
||||
else
|
||||
val =
|
||||
line[i * 2 * channels + 2 * j + 1] * 256 +
|
||||
line[i * 2 * channels + 2 * j];
|
||||
avg[j] += val;
|
||||
}
|
||||
|
||||
avg[j] /= num_pixels;
|
||||
}
|
||||
for (unsigned ch = 0; ch < channels; ch++) {
|
||||
avg[ch] = 0;
|
||||
for (std::size_t x = 0; x < image.get_width(); x++) {
|
||||
avg[ch] += image.get_raw_channel(x, 0, ch);
|
||||
}
|
||||
avg[ch] /= image.get_width();
|
||||
}
|
||||
|
||||
DBG(DBG_info, "%s: average: %d,%d,%d\n", __func__, avg[0], avg[1], avg[2]);
|
||||
|
||||
|
@ -1692,9 +1503,9 @@ void CommandSetGl124::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
{
|
||||
DBG_HELPER(dbg);
|
||||
unsigned channels;
|
||||
int pass = 0, avg, total_size;
|
||||
int pass = 0, avg;
|
||||
int topavg, bottomavg, lines;
|
||||
int top, bottom, black_pixels, pixels;
|
||||
int top, bottom, black_pixels;
|
||||
|
||||
// no gain nor offset for TI AFE
|
||||
uint8_t reg0a = dev->interface->read_register(REG_0x0A);
|
||||
|
@ -1704,9 +1515,8 @@ void CommandSetGl124::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
|
||||
/* offset calibration is always done in color mode */
|
||||
channels = 3;
|
||||
dev->calib_pixels = sensor.sensor_pixels;
|
||||
lines=1;
|
||||
pixels = (sensor.sensor_pixels * sensor.optical_res) / sensor.optical_res;
|
||||
unsigned pixels = dev->model->x_size_calib_mm * sensor.optical_res / MM_PER_INCH;
|
||||
black_pixels = (sensor.black_pixels * sensor.optical_res) / sensor.optical_res;
|
||||
DBG(DBG_io2, "%s: black_pixels=%d\n", __func__, black_pixels);
|
||||
|
||||
|
@ -1725,19 +1535,14 @@ void CommandSetGl124::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::SINGLE_LINE |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
ScanFlag::IGNORE_STAGGER_OFFSET |
|
||||
ScanFlag::IGNORE_COLOR_OFFSET;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, sensor, ®s, session);
|
||||
|
||||
sanei_genesys_set_motor_power(regs, false);
|
||||
|
||||
/* allocate memory for scans */
|
||||
total_size = pixels * channels * lines * (session.params.depth / 8);
|
||||
|
||||
std::vector<uint8_t> first_line(total_size);
|
||||
std::vector<uint8_t> second_line(total_size);
|
||||
|
||||
/* init gain */
|
||||
dev->frontend.set_gain(0, 0);
|
||||
dev->frontend.set_gain(1, 0);
|
||||
|
@ -1759,16 +1564,16 @@ void CommandSetGl124::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
return;
|
||||
}
|
||||
|
||||
sanei_genesys_read_data_from_scanner(dev, first_line.data(), total_size);
|
||||
auto first_line = read_unshuffled_image_from_scanner(dev, session, session.output_line_bytes);
|
||||
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
char title[30];
|
||||
std::snprintf(title, 30, "gl124_offset%03d.pnm", bottom);
|
||||
sanei_genesys_write_pnm_file(title, first_line.data(), session.params.depth,
|
||||
channels, pixels, lines);
|
||||
sanei_genesys_write_pnm_file(title, first_line);
|
||||
}
|
||||
|
||||
bottomavg = dark_average(first_line.data(), pixels, lines, channels, black_pixels);
|
||||
bottomavg = dark_average(first_line.get_row_ptr(0), pixels, lines, channels, black_pixels);
|
||||
DBG(DBG_io2, "%s: bottom avg=%d\n", __func__, bottomavg);
|
||||
|
||||
/* now top value */
|
||||
|
@ -1780,9 +1585,10 @@ void CommandSetGl124::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
dev->interface->write_registers(regs);
|
||||
DBG(DBG_info, "%s: starting second line reading\n", __func__);
|
||||
begin_scan(dev, sensor, ®s, true);
|
||||
sanei_genesys_read_data_from_scanner(dev, second_line.data(), total_size);
|
||||
|
||||
topavg = dark_average(second_line.data(), pixels, lines, channels, black_pixels);
|
||||
auto second_line = read_unshuffled_image_from_scanner(dev, session, session.output_line_bytes);
|
||||
|
||||
topavg = dark_average(second_line.get_row_ptr(0), pixels, lines, channels, black_pixels);
|
||||
DBG(DBG_io2, "%s: top avg=%d\n", __func__, topavg);
|
||||
|
||||
/* loop until acceptable level */
|
||||
|
@ -1800,17 +1606,15 @@ void CommandSetGl124::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
dev->interface->write_registers(regs);
|
||||
DBG(DBG_info, "%s: starting second line reading\n", __func__);
|
||||
begin_scan(dev, sensor, ®s, true);
|
||||
sanei_genesys_read_data_from_scanner(dev, second_line.data(), total_size);
|
||||
second_line = read_unshuffled_image_from_scanner(dev, session, session.output_line_bytes);
|
||||
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
if (DBG_LEVEL >= DBG_data) {
|
||||
char title[30];
|
||||
std::snprintf(title, 30, "gl124_offset%03d.pnm", dev->frontend.get_offset(1));
|
||||
sanei_genesys_write_pnm_file(title, second_line.data(), session.params.depth,
|
||||
channels, pixels, lines);
|
||||
}
|
||||
sanei_genesys_write_pnm_file(title, second_line);
|
||||
}
|
||||
|
||||
avg = dark_average(second_line.data(), pixels, lines, channels, black_pixels);
|
||||
avg = dark_average(second_line.get_row_ptr(0), pixels, lines, channels, black_pixels);
|
||||
DBG(DBG_info, "%s: avg=%d offset=%d\n", __func__, avg, dev->frontend.get_offset(1));
|
||||
|
||||
/* compute new boundaries */
|
||||
|
@ -1845,12 +1649,8 @@ void CommandSetGl124::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
Genesys_Register_Set& regs, int dpi) const
|
||||
{
|
||||
DBG_HELPER_ARGS(dbg, "dpi = %d", dpi);
|
||||
int pixels;
|
||||
int total_size;
|
||||
int i, j, channels;
|
||||
int max[3];
|
||||
float gain[3],coeff;
|
||||
int val, code, lines;
|
||||
int code, lines;
|
||||
|
||||
// no gain nor offset for TI AFE
|
||||
uint8_t reg0a = dev->interface->read_register(REG_0x0A);
|
||||
|
@ -1859,7 +1659,7 @@ void CommandSetGl124::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
}
|
||||
|
||||
/* coarse gain calibration is always done in color mode */
|
||||
channels = 3;
|
||||
unsigned channels = 3;
|
||||
|
||||
if(dev->settings.xres<sensor.optical_res)
|
||||
{
|
||||
|
@ -1868,14 +1668,13 @@ void CommandSetGl124::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
coeff = 1.0f;
|
||||
}
|
||||
lines=10;
|
||||
pixels = (sensor.sensor_pixels * sensor.optical_res) / sensor.optical_res;
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = sensor.optical_res;
|
||||
session.params.yres = sensor.optical_res;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = 0;
|
||||
session.params.pixels = pixels;
|
||||
session.params.pixels = dev->model->x_size_calib_mm * sensor.optical_res / MM_PER_INCH;;
|
||||
session.params.lines = lines;
|
||||
session.params.depth = 8;
|
||||
session.params.channels = channels;
|
||||
|
@ -1885,7 +1684,8 @@ void CommandSetGl124::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::SINGLE_LINE |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
ScanFlag::IGNORE_STAGGER_OFFSET |
|
||||
ScanFlag::IGNORE_COLOR_OFFSET;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
try {
|
||||
|
@ -1899,9 +1699,7 @@ void CommandSetGl124::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
|
||||
dev->interface->write_registers(regs);
|
||||
|
||||
total_size = pixels * channels * (16 / session.params.depth) * lines;
|
||||
|
||||
std::vector<uint8_t> line(total_size);
|
||||
std::vector<uint8_t> line(session.output_line_bytes);
|
||||
|
||||
set_fe(dev, sensor, AFE_SET);
|
||||
begin_scan(dev, sensor, ®s, true);
|
||||
|
@ -1913,41 +1711,35 @@ void CommandSetGl124::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
return;
|
||||
}
|
||||
|
||||
sanei_genesys_read_data_from_scanner(dev, line.data(), total_size);
|
||||
// BUG: we probably want to read whole image, not just first line
|
||||
auto image = read_unshuffled_image_from_scanner(dev, session, session.output_line_bytes);
|
||||
|
||||
if (DBG_LEVEL >= DBG_data) {
|
||||
sanei_genesys_write_pnm_file("gl124_gain.pnm", line.data(), session.params.depth,
|
||||
channels, pixels, lines);
|
||||
sanei_genesys_write_pnm_file("gl124_gain.pnm", image);
|
||||
}
|
||||
|
||||
/* average value on each channel */
|
||||
for (j = 0; j < channels; j++)
|
||||
{
|
||||
max[j] = 0;
|
||||
for (i = pixels/4; i < (pixels*3/4); i++)
|
||||
{
|
||||
if (dev->model->is_cis) {
|
||||
val = line[i + j * pixels];
|
||||
} else {
|
||||
val = line[i * channels + j];
|
||||
}
|
||||
for (unsigned ch = 0; ch < channels; ch++) {
|
||||
|
||||
max[j] += val;
|
||||
}
|
||||
max[j] = max[j] / (pixels/2);
|
||||
auto width = image.get_width();
|
||||
|
||||
gain[j] = (static_cast<float>(sensor.gain_white_ref) * coeff) / max[j];
|
||||
std::uint64_t total = 0;
|
||||
for (std::size_t x = width / 4; x < (width * 3 / 4); x++) {
|
||||
total += image.get_raw_channel(x, 0, ch);
|
||||
}
|
||||
|
||||
total /= width / 2;
|
||||
|
||||
gain[ch] = (static_cast<float>(sensor.gain_white_ref) * coeff) / total;
|
||||
|
||||
/* turn logical gain value into gain code, checking for overflow */
|
||||
code = static_cast<int>(283 - 208 / gain[j]);
|
||||
if (code > 255)
|
||||
code = 255;
|
||||
else if (code < 0)
|
||||
code = 0;
|
||||
dev->frontend.set_gain(j, code);
|
||||
code = static_cast<int>(283 - 208 / gain[ch]);
|
||||
code = clamp(code, 0, 255);
|
||||
dev->frontend.set_gain(ch, code);
|
||||
|
||||
DBG(DBG_proc, "%s: channel %d, max=%d, gain = %f, setting:%d\n", __func__, j, max[j],
|
||||
gain[j], dev->frontend.get_gain(j));
|
||||
DBG(DBG_proc, "%s: channel %d, total=%d, gain = %f, setting:%d\n", __func__, ch,
|
||||
static_cast<unsigned>(total),
|
||||
gain[ch], dev->frontend.get_gain(ch));
|
||||
}
|
||||
|
||||
if (dev->model->is_cis) {
|
||||
|
@ -1989,9 +1781,9 @@ void CommandSetGl124::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Se
|
|||
ScanSession session;
|
||||
session.params.xres = sensor.optical_res;
|
||||
session.params.yres = dev->motor.base_ydpi;
|
||||
session.params.startx = sensor.sensor_pixels / 4;
|
||||
session.params.startx = dev->model->x_size_calib_mm * sensor.optical_res / MM_PER_INCH / 4;
|
||||
session.params.starty = 0;
|
||||
session.params.pixels = sensor.sensor_pixels / 2;
|
||||
session.params.pixels = dev->model->x_size_calib_mm * sensor.optical_res / MM_PER_INCH / 2;
|
||||
session.params.lines = 1;
|
||||
session.params.depth = 8;
|
||||
session.params.channels = *channels;
|
||||
|
@ -2001,7 +1793,8 @@ void CommandSetGl124::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Se
|
|||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::SINGLE_LINE |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
ScanFlag::IGNORE_STAGGER_OFFSET |
|
||||
ScanFlag::IGNORE_COLOR_OFFSET;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, sensor, reg, session);
|
||||
|
@ -2011,7 +1804,6 @@ void CommandSetGl124::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Se
|
|||
*total_size = num_pixels * 3 * 1; /* colors * bytes_per_color * scan lines */
|
||||
|
||||
sanei_genesys_set_motor_power(*reg, false);
|
||||
dev->interface->write_registers(*reg);
|
||||
}
|
||||
|
||||
/** @brief default GPIO values
|
||||
|
@ -2244,16 +2036,6 @@ void CommandSetGl124::eject_document(Genesys_Device* dev) const
|
|||
throw SaneException("not implemented");
|
||||
}
|
||||
|
||||
void CommandSetGl124::search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
bool forward, bool black) const
|
||||
{
|
||||
(void) dev;
|
||||
(void) sensor;
|
||||
(void) forward;
|
||||
(void) black;
|
||||
throw SaneException("not implemented");
|
||||
}
|
||||
|
||||
void CommandSetGl124::move_to_ta(Genesys_Device* dev) const
|
||||
{
|
||||
(void) dev;
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
#define BACKEND_GENESYS_GL124_H
|
||||
|
||||
#include "genesys.h"
|
||||
#include "command_set.h"
|
||||
#include "command_set_common.h"
|
||||
|
||||
namespace genesys {
|
||||
namespace gl124 {
|
||||
|
@ -112,7 +112,7 @@ static Memory_layout layouts[]={
|
|||
static void gl124_send_slope_table(Genesys_Device* dev, int table_nr,
|
||||
const std::vector<uint16_t>& slope_table, int steps);
|
||||
|
||||
class CommandSetGl124 : public CommandSet
|
||||
class CommandSetGl124 : public CommandSetCommon
|
||||
{
|
||||
public:
|
||||
~CommandSetGl124() override = default;
|
||||
|
@ -125,13 +125,11 @@ public:
|
|||
Genesys_Register_Set* regs, int* channels,
|
||||
int* total_size) const override;
|
||||
|
||||
void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg,
|
||||
|
@ -148,8 +146,6 @@ public:
|
|||
|
||||
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
|
||||
void search_start_position(Genesys_Device* dev) const override;
|
||||
|
||||
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
|
@ -175,9 +171,6 @@ public:
|
|||
|
||||
void eject_document(Genesys_Device* dev) const override;
|
||||
|
||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
bool forward, bool black) const override;
|
||||
|
||||
void move_to_ta(Genesys_Device* dev) const override;
|
||||
|
||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||
|
|
|
@ -232,9 +232,8 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
|
|||
regs->find_reg(0x01).value &= ~REG_0x01_CISSET;
|
||||
}
|
||||
|
||||
/* if device has no calibration, don't enable shading correction */
|
||||
if (dev->model->flags & GENESYS_FLAG_NO_CALIBRATION)
|
||||
{
|
||||
// if device has no calibration, don't enable shading correction
|
||||
if (has_flag(dev->model->flags, ModelFlag::NO_CALIBRATION)) {
|
||||
regs->find_reg(0x01).value &= ~REG_0x01_DVDSET;
|
||||
}
|
||||
|
||||
|
@ -317,7 +316,7 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
|
|||
sanei_genesys_set_dpihw(*regs, sensor, sensor.optical_res);
|
||||
|
||||
/* gamma enable for scans */
|
||||
if (dev->model->flags & GENESYS_FLAG_14BIT_GAMMA) {
|
||||
if (has_flag(dev->model->flags, ModelFlag::GAMMA_14BIT)) {
|
||||
regs->find_reg(0x05).value |= REG_0x05_GMM14BIT;
|
||||
}
|
||||
|
||||
|
@ -551,7 +550,7 @@ void CommandSetGl646::init_regs_for_scan_session(Genesys_Device* dev, const Gene
|
|||
dev->read_buffer.clear();
|
||||
dev->read_buffer.alloc(session.buffer_size_read);
|
||||
|
||||
build_image_pipeline(dev, session);
|
||||
build_image_pipeline(dev, sensor, session);
|
||||
|
||||
dev->read_active = true;
|
||||
|
||||
|
@ -666,7 +665,7 @@ gl646_init_regs (Genesys_Device * dev)
|
|||
dev->reg.find_reg(0x05).value = 0x00; /* 12 bits gamma, disable gamma, 24 clocks/pixel */
|
||||
sanei_genesys_set_dpihw(dev->reg, sensor, sensor.optical_res);
|
||||
|
||||
if (dev->model->flags & GENESYS_FLAG_14BIT_GAMMA) {
|
||||
if (has_flag(dev->model->flags, ModelFlag::GAMMA_14BIT)) {
|
||||
dev->reg.find_reg(0x05).value |= REG_0x05_GMM14BIT;
|
||||
}
|
||||
if (dev->model->adc_id == AdcId::AD_XP200) {
|
||||
|
@ -1473,7 +1472,7 @@ void CommandSetGl646::move_back_home(Genesys_Device* dev, bool wait_until_home)
|
|||
|
||||
if (!i) /* the loop counted down to 0, scanner still is busy */
|
||||
{
|
||||
dev->set_head_pos_unknown();
|
||||
dev->set_head_pos_unknown(ScanHeadId::PRIMARY | ScanHeadId::SECONDARY);
|
||||
throw SaneException(SANE_STATUS_DEVICE_BUSY, "motor is still on: device busy");
|
||||
}
|
||||
|
||||
|
@ -1567,7 +1566,7 @@ void CommandSetGl646::move_back_home(Genesys_Device* dev, bool wait_until_home)
|
|||
// stop the motor
|
||||
catch_all_exceptions(__func__, [&](){ gl646_stop_motor (dev); });
|
||||
catch_all_exceptions(__func__, [&](){ end_scan_impl(dev, &dev->reg, true, false); });
|
||||
dev->set_head_pos_unknown();
|
||||
dev->set_head_pos_unknown(ScanHeadId::PRIMARY | ScanHeadId::SECONDARY);
|
||||
throw SaneException(SANE_STATUS_IO_ERROR, "timeout while waiting for scanhead to go home");
|
||||
}
|
||||
|
||||
|
@ -1575,90 +1574,6 @@ void CommandSetGl646::move_back_home(Genesys_Device* dev, bool wait_until_home)
|
|||
DBG(DBG_info, "%s: scanhead is still moving\n", __func__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically set top-left edge of the scan area by scanning an
|
||||
* area at 300 dpi from very top of scanner
|
||||
* @param dev device stucture describing the scanner
|
||||
*/
|
||||
void CommandSetGl646::search_start_position(Genesys_Device* dev) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
Genesys_Settings settings;
|
||||
unsigned int resolution, x, y;
|
||||
|
||||
/* we scan at 300 dpi */
|
||||
resolution = get_closest_resolution(dev->model->sensor_id, 300, 1);
|
||||
|
||||
// FIXME: the current approach of doing search only for one resolution does not work on scanners
|
||||
// whith employ different sensors with potentially different settings.
|
||||
const auto& sensor = sanei_genesys_find_sensor(dev, resolution, 1,
|
||||
dev->model->default_method);
|
||||
|
||||
/* fill settings for a gray level scan */
|
||||
settings.scan_method = dev->model->default_method;
|
||||
settings.scan_mode = ScanColorMode::GRAY;
|
||||
settings.xres = resolution;
|
||||
settings.yres = resolution;
|
||||
settings.tl_x = 0;
|
||||
settings.tl_y = 0;
|
||||
settings.pixels = 600;
|
||||
settings.requested_pixels = settings.pixels;
|
||||
settings.lines = dev->model->search_lines;
|
||||
settings.depth = 8;
|
||||
settings.color_filter = ColorFilter::RED;
|
||||
|
||||
settings.disable_interpolation = 0;
|
||||
settings.threshold = 0;
|
||||
|
||||
// scan the desired area
|
||||
std::vector<uint8_t> data;
|
||||
simple_scan(dev, sensor, settings, true, true, false, data, "search_start_position");
|
||||
|
||||
// handle stagger case : reorder gray data and thus loose some lines
|
||||
auto staggered_lines = dev->session.num_staggered_lines;
|
||||
if (staggered_lines > 0) {
|
||||
DBG(DBG_proc, "%s: 'un-staggering'\n", __func__);
|
||||
for (y = 0; y < settings.lines - staggered_lines; y++) {
|
||||
/* one point out of 2 is 'unaligned' */
|
||||
for (x = 0; x < settings.pixels; x += 2)
|
||||
{
|
||||
data[y * settings.pixels + x] = data[(y + staggered_lines) * settings.pixels + x];
|
||||
}
|
||||
}
|
||||
/* correct line number */
|
||||
settings.lines -= staggered_lines;
|
||||
}
|
||||
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
sanei_genesys_write_pnm_file("gl646_search_position.pnm", data.data(), settings.depth, 1,
|
||||
settings.pixels, settings.lines);
|
||||
}
|
||||
|
||||
// now search reference points on the data
|
||||
for (auto& sensor_update :
|
||||
sanei_genesys_find_sensors_all_for_write(dev, dev->model->default_method))
|
||||
{
|
||||
sanei_genesys_search_reference_point(dev, sensor_update, data.data(), 0,
|
||||
resolution, settings.pixels, settings.lines);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* internally overriden during effective calibration
|
||||
* sets up register for coarse gain calibration
|
||||
*/
|
||||
void CommandSetGl646::init_regs_for_coarse_calibration(Genesys_Device* dev,
|
||||
const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
(void) dev;
|
||||
(void) sensor;
|
||||
(void) regs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* init registers for shading calibration
|
||||
* we assume that scanner's head is on an area suiting shading calibration.
|
||||
|
@ -1694,10 +1609,13 @@ void CommandSetGl646::init_regs_for_shading(Genesys_Device* dev, const Genesys_S
|
|||
settings.yres = settings.xres;
|
||||
settings.tl_x = 0;
|
||||
settings.tl_y = 0;
|
||||
settings.pixels = (calib_sensor.sensor_pixels * settings.xres) / calib_sensor.optical_res;
|
||||
settings.pixels = dev->model->x_size_calib_mm * settings.xres / MM_PER_INCH;
|
||||
settings.requested_pixels = settings.pixels;
|
||||
dev->calib_lines = dev->model->shading_lines;
|
||||
settings.lines = dev->calib_lines * (3 - ccd_size_divisor);
|
||||
|
||||
unsigned calib_lines =
|
||||
static_cast<unsigned>(dev->model->y_size_calib_mm * settings.yres / MM_PER_INCH);
|
||||
settings.lines = calib_lines;
|
||||
|
||||
settings.depth = 16;
|
||||
settings.color_filter = dev->settings.color_filter;
|
||||
|
||||
|
@ -1706,14 +1624,8 @@ void CommandSetGl646::init_regs_for_shading(Genesys_Device* dev, const Genesys_S
|
|||
|
||||
// we don't want top offset, but we need right margin to be the same than the one for the final
|
||||
// scan
|
||||
setup_for_scan(dev, calib_sensor, &dev->reg, settings, true, false, false, false);
|
||||
|
||||
/* used when sending shading calibration data */
|
||||
dev->calib_pixels = settings.pixels;
|
||||
dev->calib_channels = dev->session.params.channels;
|
||||
if (!dev->model->is_cis) {
|
||||
dev->calib_channels = 3;
|
||||
}
|
||||
dev->calib_session = setup_for_scan(dev, calib_sensor, &dev->reg, settings,
|
||||
true, false, false, false);
|
||||
|
||||
/* no shading */
|
||||
dev->reg.find_reg(0x01).value &= ~REG_0x01_DVDSET;
|
||||
|
@ -1725,14 +1637,11 @@ void CommandSetGl646::init_regs_for_shading(Genesys_Device* dev, const Genesys_S
|
|||
/* TODO another flag to setup regs ? */
|
||||
/* enforce needed LINCNT, getting rid of extra lines for color reordering */
|
||||
if (!dev->model->is_cis) {
|
||||
dev->reg.set24(REG_LINCNT, dev->calib_lines);
|
||||
dev->reg.set24(REG_LINCNT, calib_lines);
|
||||
} else {
|
||||
dev->reg.set24(REG_LINCNT, dev->calib_lines * 3);
|
||||
dev->reg.set24(REG_LINCNT, calib_lines * 3);
|
||||
}
|
||||
|
||||
/* copy reg to calib_reg */
|
||||
dev->calib_reg = dev->reg;
|
||||
|
||||
DBG(DBG_info, "%s:\n\tdev->settings.xres=%d\n\tdev->settings.yres=%d\n", __func__,
|
||||
dev->settings.xres, dev->settings.yres);
|
||||
}
|
||||
|
@ -1748,7 +1657,8 @@ bool CommandSetGl646::needs_home_before_init_regs_for_scan(Genesys_Device* dev)
|
|||
* set up registers for the actual scan. The scan's parameters are given
|
||||
* through the device settings. It allocates the scan buffers.
|
||||
*/
|
||||
void CommandSetGl646::init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const
|
||||
void CommandSetGl646::init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
|
||||
|
@ -1756,11 +1666,11 @@ void CommandSetGl646::init_regs_for_scan(Genesys_Device* dev, const Genesys_Sens
|
|||
|
||||
ScanSession session = calculate_scan_session(dev, sensor, dev->settings);
|
||||
|
||||
init_regs_for_scan_session(dev, sensor, &dev->reg, session);
|
||||
init_regs_for_scan_session(dev, sensor, ®s, session);
|
||||
|
||||
/* gamma is only enabled at final scan time */
|
||||
if (dev->settings.depth < 16) {
|
||||
dev->reg.find_reg(0x05).value |= REG_0x05_GMMENB;
|
||||
regs.find_reg(0x05).value |= REG_0x05_GMMENB;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1775,14 +1685,14 @@ void CommandSetGl646::init_regs_for_scan(Genesys_Device* dev, const Genesys_Sens
|
|||
* @param xcorrection take x geometry correction into account (fixed and detected offsets)
|
||||
* @param ycorrection take y geometry correction into account
|
||||
*/
|
||||
static void setup_for_scan(Genesys_Device* dev,
|
||||
const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set*regs,
|
||||
Genesys_Settings settings,
|
||||
bool split,
|
||||
bool xcorrection,
|
||||
bool ycorrection,
|
||||
bool reverse)
|
||||
static ScanSession setup_for_scan(Genesys_Device* dev,
|
||||
const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set*regs,
|
||||
Genesys_Settings settings,
|
||||
bool split,
|
||||
bool xcorrection,
|
||||
bool ycorrection,
|
||||
bool reverse)
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
|
||||
|
@ -1794,12 +1704,12 @@ static void setup_for_scan(Genesys_Device* dev,
|
|||
if (!split) {
|
||||
if (!dev->model->is_sheetfed) {
|
||||
if (ycorrection) {
|
||||
move = static_cast<float>(dev->model->y_offset);
|
||||
move = dev->model->y_offset;
|
||||
}
|
||||
|
||||
// add tl_y to base movement
|
||||
}
|
||||
move += static_cast<float>(settings.tl_y);
|
||||
move += settings.tl_y;
|
||||
|
||||
if (move < 0) {
|
||||
DBG(DBG_error, "%s: overriding negative move value %f\n", __func__, move);
|
||||
|
@ -1809,15 +1719,15 @@ static void setup_for_scan(Genesys_Device* dev,
|
|||
move = static_cast<float>((move * dev->motor.optical_ydpi) / MM_PER_INCH);
|
||||
DBG(DBG_info, "%s: move=%f steps\n", __func__, move);
|
||||
|
||||
float start = static_cast<float>(settings.tl_x);
|
||||
float start = settings.tl_x;
|
||||
if (xcorrection) {
|
||||
if (settings.scan_method == ScanMethod::FLATBED) {
|
||||
start += static_cast<float>(dev->model->x_offset);
|
||||
start += dev->model->x_offset;
|
||||
} else {
|
||||
start += static_cast<float>(dev->model->x_offset_ta);
|
||||
start += dev->model->x_offset_ta;
|
||||
}
|
||||
}
|
||||
start = static_cast<float>((start * sensor.optical_res) / MM_PER_INCH);
|
||||
start = static_cast<float>((start * settings.xres) / MM_PER_INCH);
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = settings.xres;
|
||||
|
@ -1845,6 +1755,8 @@ static void setup_for_scan(Genesys_Device* dev,
|
|||
compute_session(dev, session, sensor);
|
||||
|
||||
dev->cmd_set->init_regs_for_scan_session(dev, sensor, regs, session);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1857,9 +1769,7 @@ void CommandSetGl646::send_gamma_table(Genesys_Device* dev, const Genesys_Sensor
|
|||
int address;
|
||||
int bits;
|
||||
|
||||
/* gamma table size */
|
||||
if (dev->model->flags & GENESYS_FLAG_14BIT_GAMMA)
|
||||
{
|
||||
if (has_flag(dev->model->flags, ModelFlag::GAMMA_14BIT)) {
|
||||
size = 16384;
|
||||
bits = 14;
|
||||
}
|
||||
|
@ -1931,7 +1841,7 @@ SensorExposure CommandSetGl646::led_calibration(Genesys_Device* dev, const Genes
|
|||
settings.yres = resolution;
|
||||
settings.tl_x = 0;
|
||||
settings.tl_y = 0;
|
||||
settings.pixels = (sensor.sensor_pixels * resolution) / sensor.optical_res;
|
||||
settings.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
|
||||
settings.requested_pixels = settings.pixels;
|
||||
settings.lines = 1;
|
||||
settings.depth = 16;
|
||||
|
@ -2105,7 +2015,7 @@ static void ad_fe_offset_calibration(Genesys_Device* dev, const Genesys_Sensor&
|
|||
settings.yres = resolution;
|
||||
settings.tl_x = 0;
|
||||
settings.tl_y = 0;
|
||||
settings.pixels = (calib_sensor.sensor_pixels * resolution) / calib_sensor.optical_res;
|
||||
settings.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
|
||||
settings.requested_pixels = settings.pixels;
|
||||
settings.lines = CALIBRATION_LINES;
|
||||
settings.depth = 8;
|
||||
|
@ -2216,7 +2126,7 @@ void CommandSetGl646::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
settings.yres = resolution;
|
||||
settings.tl_x = 0;
|
||||
settings.tl_y = 0;
|
||||
settings.pixels = (calib_sensor.sensor_pixels * resolution) / calib_sensor.optical_res;
|
||||
settings.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
|
||||
settings.requested_pixels = settings.pixels;
|
||||
settings.lines = CALIBRATION_LINES;
|
||||
settings.depth = 8;
|
||||
|
@ -2352,7 +2262,7 @@ static void ad_fe_coarse_gain_calibration(Genesys_Device* dev, const Genesys_Sen
|
|||
settings.yres = resolution;
|
||||
settings.tl_x = 0;
|
||||
settings.tl_y = 0;
|
||||
settings.pixels = (calib_sensor.sensor_pixels * resolution) / calib_sensor.optical_res;
|
||||
settings.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
|
||||
settings.requested_pixels = settings.pixels;
|
||||
settings.lines = CALIBRATION_LINES;
|
||||
settings.depth = 8;
|
||||
|
@ -2459,7 +2369,7 @@ void CommandSetGl646::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
if (settings.scan_method == ScanMethod::FLATBED)
|
||||
{
|
||||
settings.tl_x = 0;
|
||||
settings.pixels = (calib_sensor.sensor_pixels * resolution) / calib_sensor.optical_res;
|
||||
settings.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2608,7 +2518,7 @@ void CommandSetGl646::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Se
|
|||
settings.yres = resolution;
|
||||
settings.tl_x = 0;
|
||||
settings.tl_y = 0;
|
||||
settings.pixels = (local_sensor.sensor_pixels * resolution) / local_sensor.optical_res;
|
||||
settings.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
|
||||
settings.requested_pixels = settings.pixels;
|
||||
settings.lines = 2;
|
||||
settings.depth = 8;
|
||||
|
@ -2639,7 +2549,6 @@ void CommandSetGl646::init_regs_for_warmup(Genesys_Device* dev, const Genesys_Se
|
|||
|
||||
// now registers are ok, write them to scanner
|
||||
gl646_set_fe(dev, local_sensor, AFE_SET, settings.xres);
|
||||
dev->interface->write_registers(*local_reg);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2731,10 +2640,11 @@ void CommandSetGl646::init(Genesys_Device* dev) const
|
|||
gl646_init_regs (dev);
|
||||
|
||||
// Init shading data
|
||||
sanei_genesys_init_shading_data(dev, sensor, sensor.sensor_pixels);
|
||||
sanei_genesys_init_shading_data(dev, sensor,
|
||||
dev->model->x_size_calib_mm * sensor.optical_res /
|
||||
MM_PER_INCH);
|
||||
|
||||
/* initial calibration reg values */
|
||||
dev->calib_reg = dev->reg;
|
||||
dev->initial_regs = dev->reg;
|
||||
}
|
||||
|
||||
// execute physical unit init only if cold
|
||||
|
@ -2828,16 +2738,13 @@ void CommandSetGl646::init(Genesys_Device* dev) const
|
|||
|
||||
/* ensure head is correctly parked, and check lock */
|
||||
if (!dev->model->is_sheetfed) {
|
||||
if (dev->model->flags & GENESYS_FLAG_REPARK)
|
||||
{
|
||||
if (has_flag(dev->model->flags, ModelFlag::REPARK)) {
|
||||
// FIXME: if repark fails, we should print an error message that the scanner is locked and
|
||||
// the user should unlock the lock. We should also rethrow with SANE_STATUS_JAMMED
|
||||
gl646_repark_head(dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
move_back_home(dev, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* here session and device are initialized */
|
||||
|
@ -3015,7 +2922,7 @@ static void simple_move(Genesys_Device* dev, SANE_Int distance)
|
|||
settings.yres = resolution;
|
||||
settings.tl_y = 0;
|
||||
settings.tl_x = 0;
|
||||
settings.pixels = (sensor.sensor_pixels * settings.xres) / sensor.optical_res;
|
||||
settings.pixels = dev->model->x_size_calib_mm * settings.xres / MM_PER_INCH;
|
||||
settings.requested_pixels = settings.pixels;
|
||||
settings.lines = static_cast<unsigned>((distance * settings.xres) / MM_PER_INCH);
|
||||
settings.depth = 8;
|
||||
|
@ -3130,8 +3037,7 @@ void CommandSetGl646::update_hardware_sensors(Genesys_Scanner* session) const
|
|||
}
|
||||
|
||||
/* XPA detection */
|
||||
if (dev->model->flags & GENESYS_FLAG_XPA)
|
||||
{
|
||||
if (dev->model->has_method(ScanMethod::TRANSPARENCY)) {
|
||||
switch (dev->model->gpio_id) {
|
||||
case GpioId::HP3670:
|
||||
case GpioId::HP2400:
|
||||
|
@ -3208,154 +3114,6 @@ static void write_control(Genesys_Device* dev, const Genesys_Sensor& sensor, int
|
|||
dev->interface->write_buffer(0x3c, addr, control, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* search for a full width black or white strip.
|
||||
* @param dev scanner device
|
||||
* @param forward true if searching forward, false if searching backward
|
||||
* @param black true if searching for a black strip, false for a white strip
|
||||
*/
|
||||
void CommandSetGl646::search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor, bool forward,
|
||||
bool black) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
(void) sensor;
|
||||
|
||||
Genesys_Settings settings;
|
||||
int res = get_closest_resolution(dev->model->sensor_id, 75, 1);
|
||||
unsigned int pass, count, found, x, y;
|
||||
char title[80];
|
||||
|
||||
const auto& calib_sensor = sanei_genesys_find_sensor(dev, res, 1, ScanMethod::FLATBED);
|
||||
|
||||
/* we set up for a lowest available resolution color grey scan, full width */
|
||||
settings.scan_method = dev->model->default_method;
|
||||
settings.scan_mode = ScanColorMode::GRAY;
|
||||
settings.xres = res;
|
||||
settings.yres = res;
|
||||
settings.tl_x = 0;
|
||||
settings.tl_y = 0;
|
||||
settings.pixels = static_cast<unsigned>((dev->model->x_size * res) / MM_PER_INCH);
|
||||
settings.pixels /= calib_sensor.get_ccd_size_divisor_for_dpi(res);
|
||||
settings.requested_pixels = settings.pixels;
|
||||
|
||||
/* 15 mm at at time */
|
||||
settings.lines = static_cast<unsigned>((15 * settings.yres) / MM_PER_INCH);
|
||||
settings.depth = 8;
|
||||
settings.color_filter = ColorFilter::RED;
|
||||
|
||||
settings.disable_interpolation = 0;
|
||||
settings.threshold = 0;
|
||||
|
||||
/* signals if a strip of the given color has been found */
|
||||
found = 0;
|
||||
|
||||
/* detection pass done */
|
||||
pass = 0;
|
||||
|
||||
std::vector<uint8_t> data;
|
||||
|
||||
/* loop until strip is found or maximum pass number done */
|
||||
while (pass < 20 && !found)
|
||||
{
|
||||
// scan a full width strip
|
||||
simple_scan(dev, calib_sensor, settings, true, forward, false, data, "search_strip");
|
||||
|
||||
if (is_testing_mode()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
std::sprintf(title, "gl646_search_strip_%s%02d.pnm", forward ? "fwd" : "bwd", pass);
|
||||
sanei_genesys_write_pnm_file (title, data.data(), settings.depth, 1,
|
||||
settings.pixels, settings.lines);
|
||||
}
|
||||
|
||||
/* search data to find black strip */
|
||||
/* when searching forward, we only need one line of the searched color since we
|
||||
* will scan forward. But when doing backward search, we need all the area of the
|
||||
* same color */
|
||||
if (forward)
|
||||
{
|
||||
for (y = 0; y < settings.lines && !found; y++)
|
||||
{
|
||||
count = 0;
|
||||
/* count of white/black pixels depending on the color searched */
|
||||
for (x = 0; x < settings.pixels; x++)
|
||||
{
|
||||
/* when searching for black, detect white pixels */
|
||||
if (black && data[y * settings.pixels + x] > 90)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
/* when searching for white, detect black pixels */
|
||||
if (!black && data[y * settings.pixels + x] < 60)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* at end of line, if count >= 3%, line is not fully of the desired color
|
||||
* so we must go to next line of the buffer */
|
||||
/* count*100/pixels < 3 */
|
||||
if ((count * 100) / settings.pixels < 3)
|
||||
{
|
||||
found = 1;
|
||||
DBG(DBG_data, "%s: strip found forward during pass %d at line %d\n", __func__,
|
||||
pass, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG(DBG_data, "%s: pixels=%d, count=%d\n", __func__, settings.pixels, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* since calibration scans are done forward, we need the whole area
|
||||
to be of the required color when searching backward */
|
||||
{
|
||||
count = 0;
|
||||
for (y = 0; y < settings.lines; y++)
|
||||
{
|
||||
/* count of white/black pixels depending on the color searched */
|
||||
for (x = 0; x < settings.pixels; x++)
|
||||
{
|
||||
/* when searching for black, detect white pixels */
|
||||
if (black && data[y * settings.pixels + x] > 60)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
/* when searching for white, detect black pixels */
|
||||
if (!black && data[y * settings.pixels + x] < 60)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* at end of area, if count >= 3%, area is not fully of the desired color
|
||||
* so we must go to next buffer */
|
||||
if ((count * 100) / (settings.pixels * settings.lines) < 3)
|
||||
{
|
||||
found = 1;
|
||||
DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG(DBG_data, "%s: pixels=%d, count=%d\n", __func__, settings.pixels, count);
|
||||
}
|
||||
}
|
||||
pass++;
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
DBG(DBG_info, "%s: strip found\n", __func__);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw SaneException(SANE_STATUS_UNSUPPORTED, "%s strip not found", black ? "black" : "white");
|
||||
}
|
||||
}
|
||||
|
||||
void CommandSetGl646::wait_for_motor_stop(Genesys_Device* dev) const
|
||||
{
|
||||
(void) dev;
|
||||
|
@ -3379,10 +3137,10 @@ ScanSession CommandSetGl646::calculate_scan_session(const Genesys_Device* dev,
|
|||
float move = 0;
|
||||
// XXX STEF XXX MD5345 -> optical_ydpi, other base_ydpi => half/full step ? */
|
||||
if (!dev->model->is_sheetfed) {
|
||||
move = static_cast<float>(dev->model->y_offset);
|
||||
move = dev->model->y_offset;
|
||||
// add tl_y to base movement
|
||||
}
|
||||
move += static_cast<float>(settings.tl_y);
|
||||
move += settings.tl_y;
|
||||
|
||||
if (move < 0) {
|
||||
DBG(DBG_error, "%s: overriding negative move value %f\n", __func__, move);
|
||||
|
@ -3390,13 +3148,13 @@ ScanSession CommandSetGl646::calculate_scan_session(const Genesys_Device* dev,
|
|||
}
|
||||
|
||||
move = static_cast<float>((move * dev->motor.optical_ydpi) / MM_PER_INCH);
|
||||
float start = static_cast<float>(settings.tl_x);
|
||||
float start = settings.tl_x;
|
||||
if (settings.scan_method == ScanMethod::FLATBED) {
|
||||
start += static_cast<float>(dev->model->x_offset);
|
||||
start += dev->model->x_offset;
|
||||
} else {
|
||||
start += static_cast<float>(dev->model->x_offset_ta);
|
||||
start += dev->model->x_offset_ta;
|
||||
}
|
||||
start = static_cast<float>((start * sensor.optical_res) / MM_PER_INCH);
|
||||
start = static_cast<float>((start * settings.xres) / MM_PER_INCH);
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = settings.xres;
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
#define BACKEND_GENESYS_GL646_H
|
||||
|
||||
#include "genesys.h"
|
||||
#include "command_set.h"
|
||||
#include "command_set_common.h"
|
||||
#include "motor.h"
|
||||
|
||||
namespace genesys {
|
||||
|
@ -68,14 +68,14 @@ static void gl646_set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor, uint
|
|||
* @param ycorrection true if scanner's Y geometry must be taken into account to
|
||||
* compute Y, ie add top margins
|
||||
*/
|
||||
static void setup_for_scan(Genesys_Device* device,
|
||||
const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set*regs,
|
||||
Genesys_Settings settings,
|
||||
bool split,
|
||||
bool xcorrection,
|
||||
bool ycorrection,
|
||||
bool reverse);
|
||||
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
|
||||
|
@ -144,6 +144,10 @@ typedef struct
|
|||
*/
|
||||
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},
|
||||
|
@ -168,8 +172,8 @@ static Motor_Master motor_master[] = {
|
|||
MotorSlope::create_from_steps(15937, 6375, 3),
|
||||
MotorSlope::create_from_steps(3399, 337, 192), 192},
|
||||
|
||||
{MotorId::HP3670,2400, 3, StepType::HALF, false, true, 0,
|
||||
MotorSlope::create_from_steps(15937, 12750, 3),
|
||||
{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,
|
||||
|
@ -196,10 +200,6 @@ static Motor_Master motor_master[] = {
|
|||
MotorSlope::create_from_steps(15937, 6375, 3),
|
||||
MotorSlope::create_from_steps(3399, 337, 192), 192},
|
||||
|
||||
{MotorId::HP3670,2400, 3, StepType::HALF, false, true, 0,
|
||||
MotorSlope::create_from_steps(15937, 12750, 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),
|
||||
|
@ -436,7 +436,7 @@ static Motor_Master motor_master[] = {
|
|||
MotorSlope::create_from_steps(2000, 300, 255), 146}, /* 5500 guessed */
|
||||
};
|
||||
|
||||
class CommandSetGl646 : public CommandSet
|
||||
class CommandSetGl646 : public CommandSetCommon
|
||||
{
|
||||
public:
|
||||
~CommandSetGl646() override = default;
|
||||
|
@ -449,13 +449,11 @@ public:
|
|||
Genesys_Register_Set* regs, int* channels,
|
||||
int* total_size) const override;
|
||||
|
||||
void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg,
|
||||
|
@ -472,8 +470,6 @@ public:
|
|||
|
||||
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
|
||||
void search_start_position(Genesys_Device* dev) const override;
|
||||
|
||||
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
|
@ -495,9 +491,6 @@ public:
|
|||
|
||||
void eject_document(Genesys_Device* dev) const override;
|
||||
|
||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
bool forward, bool black) const override;
|
||||
|
||||
void move_to_ta(Genesys_Device* dev) const override;
|
||||
|
||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -42,7 +42,7 @@
|
|||
*/
|
||||
|
||||
#include "genesys.h"
|
||||
#include "command_set.h"
|
||||
#include "command_set_common.h"
|
||||
|
||||
#ifndef BACKEND_GENESYS_GL841_H
|
||||
#define BACKEND_GENESYS_GL841_H
|
||||
|
@ -50,7 +50,7 @@
|
|||
namespace genesys {
|
||||
namespace gl841 {
|
||||
|
||||
class CommandSetGl841 : public CommandSet
|
||||
class CommandSetGl841 : public CommandSetCommon
|
||||
{
|
||||
public:
|
||||
~CommandSetGl841() override = default;
|
||||
|
@ -63,13 +63,11 @@ public:
|
|||
Genesys_Register_Set* regs, int* channels,
|
||||
int* total_size) const override;
|
||||
|
||||
void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg,
|
||||
|
@ -86,8 +84,6 @@ public:
|
|||
|
||||
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
|
||||
void search_start_position(Genesys_Device* dev) const override;
|
||||
|
||||
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
|
@ -109,9 +105,6 @@ public:
|
|||
|
||||
void eject_document(Genesys_Device* dev) const override;
|
||||
|
||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
bool forward, bool black) const override;
|
||||
|
||||
void move_to_ta(Genesys_Device* dev) const override;
|
||||
|
||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -42,7 +42,7 @@
|
|||
*/
|
||||
|
||||
#include "genesys.h"
|
||||
#include "command_set.h"
|
||||
#include "command_set_common.h"
|
||||
|
||||
#ifndef BACKEND_GENESYS_GL843_H
|
||||
#define BACKEND_GENESYS_GL843_H
|
||||
|
@ -50,7 +50,7 @@
|
|||
namespace genesys {
|
||||
namespace gl843 {
|
||||
|
||||
class CommandSetGl843 : public CommandSet
|
||||
class CommandSetGl843 : public CommandSetCommon
|
||||
{
|
||||
public:
|
||||
~CommandSetGl843() override = default;
|
||||
|
@ -63,13 +63,11 @@ public:
|
|||
Genesys_Register_Set* regs, int* channels,
|
||||
int* total_size) const override;
|
||||
|
||||
void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg,
|
||||
|
@ -86,8 +84,6 @@ public:
|
|||
|
||||
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
|
||||
void search_start_position(Genesys_Device* dev) const override;
|
||||
|
||||
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
|
@ -109,9 +105,6 @@ public:
|
|||
|
||||
void eject_document(Genesys_Device* dev) const override;
|
||||
|
||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
bool forward, bool black) const override;
|
||||
|
||||
void move_to_ta(Genesys_Device* dev) const override;
|
||||
|
||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||
|
|
|
@ -338,6 +338,16 @@ static constexpr RegAddr REG_CK4MAP = 0x7a;
|
|||
|
||||
static constexpr RegAddr REG_0x7E = 0x7e;
|
||||
|
||||
static constexpr RegAddr REG_0x80 = 0x80;
|
||||
static constexpr RegMask REG_0x80_TABLE1_NORMAL = 0x03;
|
||||
static constexpr RegShift REG_0x80S_TABLE1_NORMAL = 0;
|
||||
static constexpr RegMask REG_0x80_TABLE2_BACK = 0x0c;
|
||||
static constexpr RegShift REG_0x80S_TABLE2_BACK = 2;
|
||||
static constexpr RegMask REG_0x80_TABLE4_FAST = 0x30;
|
||||
static constexpr RegShift REG_0x80S_TABLE4_FAST = 4;
|
||||
static constexpr RegMask REG_0x80_TABLE5_GO_HOME = 0xc0;
|
||||
static constexpr RegShift REG_0x80S_TABLE5_GO_HOME = 6;
|
||||
|
||||
static constexpr RegAddr REG_0x9D = 0x9d;
|
||||
static constexpr RegShift REG_0x9DS_STEPTIM = 2;
|
||||
|
||||
|
|
|
@ -217,9 +217,6 @@ gl846_init_registers (Genesys_Device * dev)
|
|||
|
||||
const auto& sensor = sanei_genesys_find_sensor_any(dev);
|
||||
sanei_genesys_set_dpihw(dev->reg, sensor, sensor.optical_res);
|
||||
|
||||
/* initalize calibration reg */
|
||||
dev->calib_reg = dev->reg;
|
||||
}
|
||||
|
||||
/**@brief send slope table for motor movement
|
||||
|
@ -236,7 +233,6 @@ static void gl846_send_slope_table(Genesys_Device* dev, int table_nr,
|
|||
{
|
||||
DBG_HELPER_ARGS(dbg, "table_nr = %d, steps = %d", table_nr, steps);
|
||||
int i;
|
||||
char msg[10000];
|
||||
|
||||
/* sanity check */
|
||||
if(table_nr<0 || table_nr>4)
|
||||
|
@ -251,16 +247,6 @@ static void gl846_send_slope_table(Genesys_Device* dev, int table_nr,
|
|||
table[i * 2 + 1] = slope_table[i] >> 8;
|
||||
}
|
||||
|
||||
if (DBG_LEVEL >= DBG_io)
|
||||
{
|
||||
std::sprintf(msg, "write slope %d (%d)=", table_nr, steps);
|
||||
for (i = 0; i < steps; i++)
|
||||
{
|
||||
std::sprintf(msg+strlen(msg), "%d", slope_table[i]);
|
||||
}
|
||||
DBG (DBG_io, "%s: %s\n", __func__, msg);
|
||||
}
|
||||
|
||||
if (dev->interface->is_mock()) {
|
||||
dev->interface->record_slope_table(table_nr, slope_table);
|
||||
}
|
||||
|
@ -327,7 +313,7 @@ void CommandSetGl846::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
|||
static void gl846_init_motor_regs_scan(Genesys_Device* dev,
|
||||
const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg,
|
||||
const Motor_Profile& motor_profile,
|
||||
const MotorProfile& motor_profile,
|
||||
unsigned int scan_exposure_time,
|
||||
unsigned scan_yres,
|
||||
unsigned int scan_lines,
|
||||
|
@ -400,7 +386,7 @@ static void gl846_init_motor_regs_scan(Genesys_Device* dev,
|
|||
fast_step_type = StepType::QUARTER;
|
||||
}
|
||||
|
||||
Motor_Profile fast_motor_profile = motor_profile;
|
||||
MotorProfile fast_motor_profile = motor_profile;
|
||||
fast_motor_profile.step_type = fast_step_type;
|
||||
|
||||
auto fast_table = sanei_genesys_slope_table(dev->model->asic_type, fast_dpi,
|
||||
|
@ -579,7 +565,7 @@ static void gl846_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
|
|||
r = sanei_genesys_get_address(reg, REG_0x01);
|
||||
r->value |= REG_0x01_SHDAREA;
|
||||
if (has_flag(session.params.flags, ScanFlag::DISABLE_SHADING) ||
|
||||
(dev->model->flags & GENESYS_FLAG_NO_CALIBRATION))
|
||||
has_flag(dev->model->flags, ModelFlag::NO_CALIBRATION))
|
||||
{
|
||||
r->value &= ~REG_0x01_DVDSET;
|
||||
}
|
||||
|
@ -665,7 +651,7 @@ static void gl846_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
|
|||
reg->set16(REG_STRPIXEL, session.pixel_startx);
|
||||
reg->set16(REG_ENDPIXEL, session.pixel_endx);
|
||||
|
||||
build_image_pipeline(dev, session);
|
||||
build_image_pipeline(dev, sensor, session);
|
||||
|
||||
/* MAXWD is expressed in 4 words unit */
|
||||
// BUG: we shouldn't multiply by channels here
|
||||
|
@ -705,9 +691,7 @@ void CommandSetGl846::init_regs_for_scan_session(Genesys_Device* dev, const Gene
|
|||
slope_dpi = slope_dpi * (1 + dummy);
|
||||
|
||||
exposure_time = sensor.exposure_lperiod;
|
||||
const auto& motor_profile = sanei_genesys_get_motor_profile(*gl846_motor_profiles,
|
||||
dev->model->motor_id,
|
||||
exposure_time);
|
||||
const auto& motor_profile = get_motor_profile(dev->motor.profiles, exposure_time, session);
|
||||
|
||||
DBG(DBG_info, "%s : exposure_time=%d pixels\n", __func__, exposure_time);
|
||||
DBG(DBG_info, "%s : scan_step_type=%d\n", __func__,
|
||||
|
@ -736,9 +720,7 @@ void CommandSetGl846::init_regs_for_scan_session(Genesys_Device* dev, const Gene
|
|||
}
|
||||
|
||||
gl846_init_motor_regs_scan(dev, sensor, reg, motor_profile, exposure_time, slope_dpi,
|
||||
dev->model->is_cis ? session.output_line_count * session.params.channels
|
||||
: session.output_line_count,
|
||||
dummy, move, mflags);
|
||||
session.optical_line_count, dummy, move, mflags);
|
||||
|
||||
/*** prepares data reordering ***/
|
||||
|
||||
|
@ -759,21 +741,33 @@ ScanSession CommandSetGl846::calculate_scan_session(const Genesys_Device* dev,
|
|||
const Genesys_Sensor& sensor,
|
||||
const Genesys_Settings& settings) const
|
||||
{
|
||||
int start;
|
||||
|
||||
DBG(DBG_info, "%s ", __func__);
|
||||
debug_dump(DBG_info, settings);
|
||||
|
||||
/* start */
|
||||
start = static_cast<int>(dev->model->x_offset);
|
||||
start += static_cast<int>(settings.tl_x);
|
||||
start = static_cast<int>((start * sensor.optical_res) / MM_PER_INCH);
|
||||
/* Steps to move to reach scanning area:
|
||||
|
||||
- first we move to physical start of scanning either by a fixed steps amount from the
|
||||
black strip or by a fixed amount from parking position, minus the steps done during
|
||||
shading calibration.
|
||||
|
||||
- then we move by the needed offset whitin physical scanning area
|
||||
*/
|
||||
unsigned move_dpi = dev->motor.base_ydpi;
|
||||
|
||||
float move = dev->model->y_offset;
|
||||
move = move + settings.tl_y;
|
||||
move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
|
||||
move -= dev->head_pos(ScanHeadId::PRIMARY);
|
||||
|
||||
float start = dev->model->x_offset;
|
||||
start = start + dev->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 = start; // not used
|
||||
session.params.starty = 0; // not used
|
||||
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;
|
||||
|
@ -782,7 +776,8 @@ ScanSession CommandSetGl846::calculate_scan_session(const Genesys_Device* dev,
|
|||
session.params.scan_method = settings.scan_method;
|
||||
session.params.scan_mode = settings.scan_mode;
|
||||
session.params.color_filter = settings.color_filter;
|
||||
session.params.flags = ScanFlag::NONE;
|
||||
// backtracking isn't handled well, so don't enable it
|
||||
session.params.flags = ScanFlag::DISABLE_BUFFER_FULL_MOVE;
|
||||
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
|
@ -817,10 +812,7 @@ void CommandSetGl846::begin_scan(Genesys_Device* dev, const Genesys_Sensor& sens
|
|||
dev->interface->write_register(REG_0x6C, val);
|
||||
*/
|
||||
|
||||
val = REG_0x0D_CLRLNCNT;
|
||||
dev->interface->write_register(REG_0x0D, val);
|
||||
val = REG_0x0D_CLRMCNT;
|
||||
dev->interface->write_register(REG_0x0D, val);
|
||||
scanner_clear_scan_and_feed_counts(*dev);
|
||||
|
||||
val = dev->interface->read_register(REG_0x01);
|
||||
val |= REG_0x01_SCAN;
|
||||
|
@ -852,120 +844,6 @@ void CommandSetGl846::move_back_home(Genesys_Device* dev, bool wait_until_home)
|
|||
scanner_move_back_home(*dev, wait_until_home);
|
||||
}
|
||||
|
||||
// Automatically set top-left edge of the scan area by scanning a 200x200 pixels area at 600 dpi
|
||||
// from very top of scanner
|
||||
void CommandSetGl846::search_start_position(Genesys_Device* dev) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
int size;
|
||||
Genesys_Register_Set local_reg;
|
||||
|
||||
int pixels = 600;
|
||||
int dpi = 300;
|
||||
|
||||
local_reg = dev->reg;
|
||||
|
||||
/* sets for a 200 lines * 600 pixels */
|
||||
/* normal scan with no shading */
|
||||
|
||||
// FIXME: the current approach of doing search only for one resolution does not work on scanners
|
||||
// whith employ different sensors with potentially different settings.
|
||||
const auto& sensor = sanei_genesys_find_sensor(dev, dpi, 1, dev->model->default_method);
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = dpi;
|
||||
session.params.yres = dpi;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = 0; /*we should give a small offset here~60 steps */
|
||||
session.params.pixels = 600;
|
||||
session.params.lines = dev->model->search_lines;
|
||||
session.params.depth = 8;
|
||||
session.params.channels = 1;
|
||||
session.params.scan_method = dev->settings.scan_method;
|
||||
session.params.scan_mode = ScanColorMode::GRAY;
|
||||
session.params.color_filter = ColorFilter::GREEN;
|
||||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, sensor, &local_reg, session);
|
||||
|
||||
// send to scanner
|
||||
dev->interface->write_registers(local_reg);
|
||||
|
||||
size = pixels * dev->model->search_lines;
|
||||
|
||||
std::vector<uint8_t> data(size);
|
||||
|
||||
begin_scan(dev, sensor, &local_reg, true);
|
||||
|
||||
if (is_testing_mode()) {
|
||||
dev->interface->test_checkpoint("search_start_position");
|
||||
end_scan(dev, &local_reg, true);
|
||||
dev->reg = local_reg;
|
||||
return;
|
||||
}
|
||||
|
||||
wait_until_buffer_non_empty(dev);
|
||||
|
||||
// now we're on target, we can read data
|
||||
sanei_genesys_read_data_from_scanner(dev, data.data(), size);
|
||||
|
||||
if (DBG_LEVEL >= DBG_data) {
|
||||
sanei_genesys_write_pnm_file("gl846_search_position.pnm", data.data(), 8, 1, pixels,
|
||||
dev->model->search_lines);
|
||||
}
|
||||
|
||||
end_scan(dev, &local_reg, true);
|
||||
|
||||
/* update regs to copy ASIC internal state */
|
||||
dev->reg = local_reg;
|
||||
|
||||
// TODO: find out where sanei_genesys_search_reference_point stores information,
|
||||
// and use that correctly
|
||||
for (auto& sensor_update :
|
||||
sanei_genesys_find_sensors_all_for_write(dev, dev->model->default_method))
|
||||
{
|
||||
sanei_genesys_search_reference_point(dev, sensor_update, data.data(), 0, dpi, pixels,
|
||||
dev->model->search_lines);
|
||||
}
|
||||
}
|
||||
|
||||
// sets up register for coarse gain calibration
|
||||
// todo: check it for scanners using it
|
||||
void CommandSetGl846::init_regs_for_coarse_calibration(Genesys_Device* dev,
|
||||
const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = dev->settings.xres;
|
||||
session.params.yres = dev->settings.yres;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = 0;
|
||||
session.params.pixels = sensor.optical_res / sensor.ccd_pixels_per_system_pixel();
|
||||
session.params.lines = 20;
|
||||
session.params.depth = 16;
|
||||
session.params.channels = dev->settings.get_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 = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::SINGLE_LINE |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, sensor, ®s, session);
|
||||
|
||||
DBG(DBG_info, "%s: optical sensor res: %d dpi, actual res: %d\n", __func__,
|
||||
sensor.optical_res / sensor.ccd_pixels_per_system_pixel(), dev->settings.xres);
|
||||
|
||||
dev->interface->write_registers(regs);
|
||||
}
|
||||
|
||||
// init registers for shading calibration
|
||||
void CommandSetGl846::init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const
|
||||
|
@ -973,136 +851,71 @@ void CommandSetGl846::init_regs_for_shading(Genesys_Device* dev, const Genesys_S
|
|||
DBG_HELPER(dbg);
|
||||
float move;
|
||||
|
||||
dev->calib_channels = 3;
|
||||
unsigned channels = 3;
|
||||
unsigned resolution = sensor.get_register_hwdpi(dev->settings.xres);
|
||||
|
||||
/* initial calibration reg values */
|
||||
regs = dev->reg;
|
||||
|
||||
dev->calib_resolution = sensor.get_register_hwdpi(dev->settings.xres);
|
||||
|
||||
const auto& calib_sensor = sanei_genesys_find_sensor(dev, dev->calib_resolution,
|
||||
dev->calib_channels,
|
||||
const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
|
||||
dev->settings.scan_method);
|
||||
dev->calib_total_bytes_to_read = 0;
|
||||
dev->calib_lines = dev->model->shading_lines;
|
||||
if (dev->calib_resolution==4800) {
|
||||
dev->calib_lines *= 2;
|
||||
}
|
||||
dev->calib_pixels = (calib_sensor.sensor_pixels * dev->calib_resolution) /
|
||||
calib_sensor.optical_res;
|
||||
|
||||
DBG(DBG_io, "%s: calib_lines = %zu\n", __func__, dev->calib_lines);
|
||||
DBG(DBG_io, "%s: calib_pixels = %zu\n", __func__, dev->calib_pixels);
|
||||
unsigned calib_lines =
|
||||
static_cast<unsigned>(dev->model->y_size_calib_mm * resolution / MM_PER_INCH);
|
||||
|
||||
/* this is aworkaround insufficent distance for slope
|
||||
* motor acceleration TODO special motor slope for shading */
|
||||
move=1;
|
||||
if(dev->calib_resolution<1200)
|
||||
{
|
||||
if (resolution < 1200) {
|
||||
move=40;
|
||||
}
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = dev->calib_resolution;
|
||||
session.params.yres = dev->calib_resolution;
|
||||
session.params.xres = resolution;
|
||||
session.params.yres = resolution;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = static_cast<unsigned>(move);
|
||||
session.params.pixels = dev->calib_pixels;
|
||||
session.params.lines = dev->calib_lines;
|
||||
session.params.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;
|
||||
session.params.lines = calib_lines;
|
||||
session.params.depth = 16;
|
||||
session.params.channels = dev->calib_channels;
|
||||
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 = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::DISABLE_BUFFER_FULL_MOVE |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
ScanFlag::DISABLE_BUFFER_FULL_MOVE;
|
||||
compute_session(dev, session, calib_sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, calib_sensor, ®s, session);
|
||||
|
||||
dev->interface->write_registers(regs);
|
||||
|
||||
/* we use GENESYS_FLAG_SHADING_REPARK */
|
||||
/* we use ModelFlag::SHADING_REPARK */
|
||||
dev->set_head_pos_zero(ScanHeadId::PRIMARY);
|
||||
|
||||
dev->calib_session = session;
|
||||
}
|
||||
|
||||
/** @brief set up registers for the actual scan
|
||||
*/
|
||||
void CommandSetGl846::init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const
|
||||
void CommandSetGl846::init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
float move;
|
||||
int move_dpi;
|
||||
float start;
|
||||
|
||||
debug_dump(DBG_info, dev->settings);
|
||||
auto session = calculate_scan_session(dev, sensor, dev->settings);
|
||||
|
||||
/* steps to move to reach scanning area:
|
||||
- first we move to physical start of scanning
|
||||
either by a fixed steps amount from the black strip
|
||||
or by a fixed amount from parking position,
|
||||
minus the steps done during shading calibration
|
||||
- then we move by the needed offset whitin physical
|
||||
scanning area
|
||||
/* Fast move to scan area:
|
||||
|
||||
assumption: steps are expressed at maximum motor resolution
|
||||
|
||||
we need:
|
||||
float y_offset;
|
||||
float y_size;
|
||||
float y_offset_calib;
|
||||
mm_to_steps()=motor dpi / 2.54 / 10=motor dpi / MM_PER_INCH */
|
||||
|
||||
/* if scanner uses GENESYS_FLAG_SEARCH_START y_offset is
|
||||
relative from origin, else, it is from parking position */
|
||||
|
||||
move_dpi = dev->motor.base_ydpi;
|
||||
|
||||
move = static_cast<float>(dev->model->y_offset);
|
||||
move = static_cast<float>(move + dev->settings.tl_y);
|
||||
move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
|
||||
move -= dev->head_pos(ScanHeadId::PRIMARY);
|
||||
DBG(DBG_info, "%s: move=%f steps\n", __func__, move);
|
||||
|
||||
/* fast move to scan area */
|
||||
/* we don't move fast the whole distance since it would involve
|
||||
* computing acceleration/deceleration distance for scan
|
||||
* resolution. So leave a remainder for it so scan makes the final
|
||||
* move tuning */
|
||||
if (dev->settings.get_channels() * dev->settings.yres >= 600 && move > 700) {
|
||||
scanner_move(*dev, dev->model->default_method, static_cast<unsigned>(move - 500),
|
||||
We don't move fast the whole distance since it would involve computing
|
||||
acceleration/deceleration distance for scan resolution. So leave a remainder for it so
|
||||
scan makes the final move tuning
|
||||
*/
|
||||
if (dev->settings.get_channels() * dev->settings.yres >= 600 && session.params.starty > 700) {
|
||||
scanner_move(*dev, dev->model->default_method,
|
||||
static_cast<unsigned>(session.params.starty - 500),
|
||||
Direction::FORWARD);
|
||||
move=500;
|
||||
session.params.starty = 500;
|
||||
}
|
||||
|
||||
DBG(DBG_info, "%s: move=%f steps\n", __func__, move);
|
||||
DBG(DBG_info, "%s: move=%f steps\n", __func__, move);
|
||||
|
||||
/* start */
|
||||
start = static_cast<float>(dev->model->x_offset);
|
||||
start = static_cast<float>(start + dev->settings.tl_x);
|
||||
start = static_cast<float>((start * sensor.optical_res) / MM_PER_INCH);
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = dev->settings.xres;
|
||||
session.params.yres = dev->settings.yres;
|
||||
session.params.startx = static_cast<unsigned>(start);
|
||||
session.params.starty = static_cast<unsigned>(move);
|
||||
session.params.pixels = dev->settings.pixels;
|
||||
session.params.requested_pixels = dev->settings.requested_pixels;
|
||||
session.params.lines = dev->settings.lines;
|
||||
session.params.depth = dev->settings.depth;
|
||||
session.params.channels = dev->settings.get_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;
|
||||
// backtracking isn't handled well, so don't enable it
|
||||
session.params.flags = ScanFlag::DISABLE_BUFFER_FULL_MOVE;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, sensor, &dev->reg, session);
|
||||
init_regs_for_scan_session(dev, sensor, ®s, session);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1193,17 +1006,13 @@ SensorExposure CommandSetGl846::led_calibration(Genesys_Device* dev, const Genes
|
|||
Genesys_Register_Set& regs) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
int num_pixels;
|
||||
int total_size;
|
||||
int used_res;
|
||||
int i, j;
|
||||
int val;
|
||||
int channels;
|
||||
int i;
|
||||
int avg[3], top[3], bottom[3];
|
||||
int turn;
|
||||
uint16_t exp[3];
|
||||
|
||||
float move = static_cast<float>(dev->model->y_offset_calib_white);
|
||||
float move = dev->model->y_offset_calib_white;
|
||||
move = static_cast<float>((move * (dev->motor.base_ydpi / 4)) / MM_PER_INCH);
|
||||
if(move>20)
|
||||
{
|
||||
|
@ -1213,11 +1022,10 @@ SensorExposure CommandSetGl846::led_calibration(Genesys_Device* dev, const Genes
|
|||
DBG(DBG_io, "%s: move=%f steps\n", __func__, move);
|
||||
|
||||
/* offset calibration is always done in color mode */
|
||||
channels = 3;
|
||||
unsigned channels = 3;
|
||||
used_res = sensor.get_register_hwdpi(dev->settings.xres);
|
||||
const auto& calib_sensor = sanei_genesys_find_sensor(dev, used_res, channels,
|
||||
dev->settings.scan_method);
|
||||
num_pixels = (calib_sensor.sensor_pixels * used_res) / calib_sensor.optical_res;
|
||||
|
||||
/* initial calibration reg values */
|
||||
regs = dev->reg;
|
||||
|
@ -1227,7 +1035,7 @@ SensorExposure CommandSetGl846::led_calibration(Genesys_Device* dev, const Genes
|
|||
session.params.yres = used_res;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = 0;
|
||||
session.params.pixels = num_pixels;
|
||||
session.params.pixels = dev->model->x_size_calib_mm * used_res / MM_PER_INCH;
|
||||
session.params.lines = 1;
|
||||
session.params.depth = 16;
|
||||
session.params.channels = channels;
|
||||
|
@ -1237,14 +1045,12 @@ SensorExposure CommandSetGl846::led_calibration(Genesys_Device* dev, const Genes
|
|||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::SINGLE_LINE |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
ScanFlag::IGNORE_STAGGER_OFFSET |
|
||||
ScanFlag::IGNORE_COLOR_OFFSET;
|
||||
compute_session(dev, session, calib_sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, calib_sensor, ®s, session);
|
||||
|
||||
total_size = num_pixels * channels * (session.params.depth / 8) * 1;
|
||||
std::vector<uint8_t> line(total_size);
|
||||
|
||||
/* initial loop values and boundaries */
|
||||
exp[0] = calib_sensor.exposure.red;
|
||||
exp[1] = calib_sensor.exposure.green;
|
||||
|
@ -1283,37 +1089,24 @@ SensorExposure CommandSetGl846::led_calibration(Genesys_Device* dev, const Genes
|
|||
return calib_sensor.exposure;
|
||||
}
|
||||
|
||||
sanei_genesys_read_data_from_scanner(dev, line.data(), total_size);
|
||||
auto image = read_unshuffled_image_from_scanner(dev, session, session.output_line_bytes);
|
||||
|
||||
// stop scanning
|
||||
scanner_stop_action(*dev);
|
||||
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
char fn[30];
|
||||
if (DBG_LEVEL >= DBG_data) {
|
||||
char fn[30];
|
||||
std::snprintf(fn, 30, "gl846_led_%02d.pnm", turn);
|
||||
sanei_genesys_write_pnm_file(fn, line.data(), session.params.depth,
|
||||
channels, num_pixels, 1);
|
||||
sanei_genesys_write_pnm_file(fn, image);
|
||||
}
|
||||
|
||||
/* compute average */
|
||||
for (j = 0; j < channels; j++)
|
||||
{
|
||||
avg[j] = 0;
|
||||
for (i = 0; i < num_pixels; i++)
|
||||
{
|
||||
if (dev->model->is_cis)
|
||||
val =
|
||||
line[i * 2 + j * 2 * num_pixels + 1] * 256 +
|
||||
line[i * 2 + j * 2 * num_pixels];
|
||||
else
|
||||
val =
|
||||
line[i * 2 * channels + 2 * j + 1] * 256 +
|
||||
line[i * 2 * channels + 2 * j];
|
||||
avg[j] += val;
|
||||
// compute average
|
||||
for (unsigned ch = 0; ch < channels; ch++) {
|
||||
avg[ch] = 0;
|
||||
for (std::size_t x = 0; x < image.get_width(); x++) {
|
||||
avg[ch] += image.get_raw_channel(x, 0, ch);
|
||||
}
|
||||
|
||||
avg[j] /= num_pixels;
|
||||
avg[ch] /= image.get_width();
|
||||
}
|
||||
|
||||
DBG(DBG_info, "%s: average: %d,%d,%d\n", __func__, avg[0], avg[1], avg[2]);
|
||||
|
@ -1529,203 +1322,6 @@ void CommandSetGl846::update_home_sensor_gpio(Genesys_Device& dev) const
|
|||
dev.interface->write_register(REG_0x6C, val);
|
||||
}
|
||||
|
||||
/** @brief search for a full width black or white strip.
|
||||
* This function searches for a black or white stripe across the scanning area.
|
||||
* When searching backward, the searched area must completely be of the desired
|
||||
* color since this area will be used for calibration which scans forward.
|
||||
* @param dev scanner device
|
||||
* @param forward true if searching forward, false if searching backward
|
||||
* @param black true if searching for a black strip, false for a white strip
|
||||
*/
|
||||
void CommandSetGl846::search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor, bool forward,
|
||||
bool black) const
|
||||
{
|
||||
DBG_HELPER_ARGS(dbg, "%s %s", black ? "black" : "white", forward ? "forward" : "reverse");
|
||||
unsigned int pixels, lines, channels;
|
||||
Genesys_Register_Set local_reg;
|
||||
size_t size;
|
||||
unsigned int pass, count, found, x, y;
|
||||
char title[80];
|
||||
|
||||
set_fe(dev, sensor, AFE_SET);
|
||||
|
||||
scanner_stop_action(*dev);
|
||||
|
||||
// set up for a gray scan at lowest dpi
|
||||
const auto& resolution_settings = dev->model->get_resolution_settings(dev->settings.scan_method);
|
||||
unsigned dpi = resolution_settings.get_min_resolution_x();
|
||||
channels = 1;
|
||||
/* 10 MM */
|
||||
/* lines = (10 * dpi) / MM_PER_INCH; */
|
||||
/* shading calibation is done with dev->motor.base_ydpi */
|
||||
lines = (dev->model->shading_lines * dpi) / dev->motor.base_ydpi;
|
||||
pixels = (sensor.sensor_pixels * dpi) / sensor.optical_res;
|
||||
|
||||
dev->set_head_pos_zero(ScanHeadId::PRIMARY);
|
||||
|
||||
local_reg = dev->reg;
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = dpi;
|
||||
session.params.yres = dpi;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = 0;
|
||||
session.params.pixels = pixels;
|
||||
session.params.lines = lines;
|
||||
session.params.depth = 8;
|
||||
session.params.channels = channels;
|
||||
session.params.scan_mode = ScanColorMode::GRAY;
|
||||
session.params.color_filter = ColorFilter::RED;
|
||||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA;
|
||||
if (!forward) {
|
||||
session.params.flags |= ScanFlag::REVERSE;
|
||||
}
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, sensor, &local_reg, session);
|
||||
|
||||
size = pixels * channels * lines * (session.params.depth / 8);
|
||||
std::vector<uint8_t> data(size);
|
||||
|
||||
dev->interface->write_registers(local_reg);
|
||||
|
||||
begin_scan(dev, sensor, &local_reg, true);
|
||||
|
||||
if (is_testing_mode()) {
|
||||
dev->interface->test_checkpoint("search_strip");
|
||||
scanner_stop_action(*dev);
|
||||
return;
|
||||
}
|
||||
|
||||
wait_until_buffer_non_empty(dev);
|
||||
|
||||
// now we're on target, we can read data
|
||||
sanei_genesys_read_data_from_scanner(dev, data.data(), size);
|
||||
|
||||
scanner_stop_action(*dev);
|
||||
|
||||
pass = 0;
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
std::sprintf(title, "gl846_search_strip_%s_%s%02d.pnm",
|
||||
black ? "black" : "white", forward ? "fwd" : "bwd", pass);
|
||||
sanei_genesys_write_pnm_file(title, data.data(), session.params.depth,
|
||||
channels, pixels, lines);
|
||||
}
|
||||
|
||||
/* loop until strip is found or maximum pass number done */
|
||||
found = 0;
|
||||
while (pass < 20 && !found)
|
||||
{
|
||||
dev->interface->write_registers(local_reg);
|
||||
|
||||
// now start scan
|
||||
begin_scan(dev, sensor, &local_reg, true);
|
||||
|
||||
wait_until_buffer_non_empty(dev);
|
||||
|
||||
// now we're on target, we can read data
|
||||
sanei_genesys_read_data_from_scanner(dev, data.data(), size);
|
||||
|
||||
scanner_stop_action(*dev);
|
||||
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
std::sprintf(title, "gl846_search_strip_%s_%s%02d.pnm",
|
||||
black ? "black" : "white", forward ? "fwd" : "bwd", pass);
|
||||
sanei_genesys_write_pnm_file(title, data.data(), session.params.depth,
|
||||
channels, pixels, lines);
|
||||
}
|
||||
|
||||
/* search data to find black strip */
|
||||
/* when searching forward, we only need one line of the searched color since we
|
||||
* will scan forward. But when doing backward search, we need all the area of the
|
||||
* same color */
|
||||
if (forward)
|
||||
{
|
||||
for (y = 0; y < lines && !found; y++)
|
||||
{
|
||||
count = 0;
|
||||
/* count of white/black pixels depending on the color searched */
|
||||
for (x = 0; x < pixels; x++)
|
||||
{
|
||||
/* when searching for black, detect white pixels */
|
||||
if (black && data[y * pixels + x] > 90)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
/* when searching for white, detect black pixels */
|
||||
if (!black && data[y * pixels + x] < 60)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* at end of line, if count >= 3%, line is not fully of the desired color
|
||||
* so we must go to next line of the buffer */
|
||||
/* count*100/pixels < 3 */
|
||||
if ((count * 100) / pixels < 3)
|
||||
{
|
||||
found = 1;
|
||||
DBG(DBG_data, "%s: strip found forward during pass %d at line %d\n", __func__,
|
||||
pass, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG(DBG_data, "%s: pixels=%d, count=%d (%d%%)\n", __func__, pixels, count,
|
||||
(100 * count) / pixels);
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* since calibration scans are done forward, we need the whole area
|
||||
to be of the required color when searching backward */
|
||||
{
|
||||
count = 0;
|
||||
for (y = 0; y < lines; y++)
|
||||
{
|
||||
/* count of white/black pixels depending on the color searched */
|
||||
for (x = 0; x < pixels; x++)
|
||||
{
|
||||
/* when searching for black, detect white pixels */
|
||||
if (black && data[y * pixels + x] > 90)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
/* when searching for white, detect black pixels */
|
||||
if (!black && data[y * pixels + x] < 60)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* at end of area, if count >= 3%, area is not fully of the desired color
|
||||
* so we must go to next buffer */
|
||||
if ((count * 100) / (pixels * lines) < 3)
|
||||
{
|
||||
found = 1;
|
||||
DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG(DBG_data, "%s: pixels=%d, count=%d (%d%%)\n", __func__, pixels, count,
|
||||
(100 * count) / pixels);
|
||||
}
|
||||
}
|
||||
pass++;
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
DBG(DBG_info, "%s: %s strip found\n", __func__, black ? "black" : "white");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw SaneException(SANE_STATUS_UNSUPPORTED, "%s strip not found", black ? "black" : "white");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* average dark pixels of a 8 bits scan
|
||||
*/
|
||||
|
@ -1768,9 +1364,9 @@ void CommandSetGl846::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
{
|
||||
DBG_HELPER(dbg);
|
||||
unsigned channels;
|
||||
int pass = 0, avg, total_size;
|
||||
int pass = 0, avg;
|
||||
int topavg, bottomavg, lines;
|
||||
int top, bottom, black_pixels, pixels;
|
||||
int top, bottom, black_pixels;
|
||||
|
||||
// no gain nor offset for AKM AFE
|
||||
uint8_t reg04 = dev->interface->read_register(REG_0x04);
|
||||
|
@ -1780,9 +1376,8 @@ void CommandSetGl846::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
|
||||
/* offset calibration is always done in color mode */
|
||||
channels = 3;
|
||||
dev->calib_pixels = sensor.sensor_pixels;
|
||||
lines=1;
|
||||
pixels = (sensor.sensor_pixels * sensor.optical_res) / sensor.optical_res;
|
||||
unsigned pixels = dev->model->x_size_calib_mm * sensor.optical_res / MM_PER_INCH;
|
||||
black_pixels = (sensor.black_pixels * sensor.optical_res) / sensor.optical_res;
|
||||
DBG(DBG_io2, "%s: black_pixels=%d\n", __func__, black_pixels);
|
||||
|
||||
|
@ -1801,18 +1396,14 @@ void CommandSetGl846::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::SINGLE_LINE |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
ScanFlag::IGNORE_STAGGER_OFFSET |
|
||||
ScanFlag::IGNORE_COLOR_OFFSET;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, sensor, ®s, session);
|
||||
|
||||
sanei_genesys_set_motor_power(regs, false);
|
||||
|
||||
total_size = pixels * channels * lines * (session.params.depth / 8);
|
||||
|
||||
std::vector<uint8_t> first_line(total_size);
|
||||
std::vector<uint8_t> second_line(total_size);
|
||||
|
||||
/* init gain */
|
||||
dev->frontend.set_gain(0, 0);
|
||||
dev->frontend.set_gain(1, 0);
|
||||
|
@ -1834,16 +1425,15 @@ void CommandSetGl846::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
return;
|
||||
}
|
||||
|
||||
sanei_genesys_read_data_from_scanner(dev, first_line.data(), total_size);
|
||||
auto first_line = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
char fn[30];
|
||||
std::snprintf(fn, 30, "gl846_offset%03d.pnm", bottom);
|
||||
sanei_genesys_write_pnm_file(fn, first_line.data(), session.params.depth,
|
||||
channels, pixels, lines);
|
||||
sanei_genesys_write_pnm_file(fn, first_line);
|
||||
}
|
||||
|
||||
bottomavg = dark_average(first_line.data(), pixels, lines, channels, black_pixels);
|
||||
bottomavg = dark_average(first_line.get_row_ptr(0), pixels, lines, channels, black_pixels);
|
||||
DBG(DBG_io2, "%s: bottom avg=%d\n", __func__, bottomavg);
|
||||
|
||||
/* now top value */
|
||||
|
@ -1855,9 +1445,9 @@ void CommandSetGl846::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
dev->interface->write_registers(regs);
|
||||
DBG(DBG_info, "%s: starting second line reading\n", __func__);
|
||||
begin_scan(dev, sensor, ®s, true);
|
||||
sanei_genesys_read_data_from_scanner(dev, second_line.data(), total_size);
|
||||
auto second_line = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
||||
|
||||
topavg = dark_average(second_line.data(), pixels, lines, channels, black_pixels);
|
||||
topavg = dark_average(second_line.get_row_ptr(0), pixels, lines, channels, black_pixels);
|
||||
DBG(DBG_io2, "%s: top avg=%d\n", __func__, topavg);
|
||||
|
||||
/* loop until acceptable level */
|
||||
|
@ -1875,17 +1465,15 @@ void CommandSetGl846::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
dev->interface->write_registers(regs);
|
||||
DBG(DBG_info, "%s: starting second line reading\n", __func__);
|
||||
begin_scan(dev, sensor, ®s, true);
|
||||
sanei_genesys_read_data_from_scanner(dev, second_line.data(), total_size);
|
||||
second_line = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
||||
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
char fn[30];
|
||||
if (DBG_LEVEL >= DBG_data) {
|
||||
char fn[30];
|
||||
std::snprintf(fn, 30, "gl846_offset%03d.pnm", dev->frontend.get_offset(1));
|
||||
sanei_genesys_write_pnm_file(fn, second_line.data(), session.params.depth,
|
||||
channels, pixels, lines);
|
||||
sanei_genesys_write_pnm_file(fn, second_line);
|
||||
}
|
||||
|
||||
avg = dark_average(second_line.data(), pixels, lines, channels, black_pixels);
|
||||
avg = dark_average(second_line.get_row_ptr(0), pixels, lines, channels, black_pixels);
|
||||
DBG(DBG_info, "%s: avg=%d offset=%d\n", __func__, avg, dev->frontend.get_offset(1));
|
||||
|
||||
/* compute new boundaries */
|
||||
|
@ -1910,12 +1498,8 @@ void CommandSetGl846::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
Genesys_Register_Set& regs, int dpi) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
int pixels;
|
||||
int total_size;
|
||||
int i, j, channels;
|
||||
int max[3];
|
||||
float gain[3],coeff;
|
||||
int val, code, lines;
|
||||
int code, lines;
|
||||
|
||||
DBG(DBG_proc, "%s: dpi = %d\n", __func__, dpi);
|
||||
|
||||
|
@ -1926,7 +1510,7 @@ void CommandSetGl846::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
}
|
||||
|
||||
/* coarse gain calibration is always done in color mode */
|
||||
channels = 3;
|
||||
unsigned channels = 3;
|
||||
|
||||
/* follow CKSEL */
|
||||
if(dev->settings.xres<sensor.optical_res)
|
||||
|
@ -1938,14 +1522,13 @@ void CommandSetGl846::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
coeff=1.0;
|
||||
}
|
||||
lines=10;
|
||||
pixels = (sensor.sensor_pixels * sensor.optical_res) / sensor.optical_res;
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = sensor.optical_res;
|
||||
session.params.yres = sensor.optical_res;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = 0;
|
||||
session.params.pixels = pixels;
|
||||
session.params.pixels = dev->model->x_size_calib_mm * sensor.optical_res / MM_PER_INCH;
|
||||
session.params.lines = lines;
|
||||
session.params.depth = 8;
|
||||
session.params.channels = channels;
|
||||
|
@ -1955,7 +1538,8 @@ void CommandSetGl846::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::SINGLE_LINE |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
ScanFlag::IGNORE_STAGGER_OFFSET |
|
||||
ScanFlag::IGNORE_COLOR_OFFSET;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
try {
|
||||
|
@ -1969,10 +1553,6 @@ void CommandSetGl846::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
|
||||
dev->interface->write_registers(regs);
|
||||
|
||||
total_size = pixels * channels * (16 / session.params.depth) * lines;
|
||||
|
||||
std::vector<uint8_t> line(total_size);
|
||||
|
||||
set_fe(dev, sensor, AFE_SET);
|
||||
begin_scan(dev, sensor, ®s, true);
|
||||
|
||||
|
@ -1983,40 +1563,33 @@ void CommandSetGl846::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
return;
|
||||
}
|
||||
|
||||
sanei_genesys_read_data_from_scanner(dev, line.data(), total_size);
|
||||
auto image = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
||||
|
||||
if (DBG_LEVEL >= DBG_data) {
|
||||
sanei_genesys_write_pnm_file("gl846_gain.pnm", line.data(), session.params.depth,
|
||||
channels, pixels, lines);
|
||||
sanei_genesys_write_pnm_file("gl846_gain.pnm", image);
|
||||
}
|
||||
|
||||
/* average value on each channel */
|
||||
for (j = 0; j < channels; j++)
|
||||
{
|
||||
max[j] = 0;
|
||||
for (i = pixels/4; i < (pixels*3/4); i++)
|
||||
{
|
||||
if (dev->model->is_cis)
|
||||
val = line[i + j * pixels];
|
||||
else
|
||||
val = line[i * channels + j];
|
||||
for (unsigned ch = 0; ch < channels; ch++) {
|
||||
|
||||
max[j] += val;
|
||||
auto width = image.get_width();
|
||||
|
||||
std::uint64_t total = 0;
|
||||
for (std::size_t x = width / 4; x < (width * 3 / 4); x++) {
|
||||
total += image.get_raw_channel(x, 0, ch);
|
||||
}
|
||||
max[j] = max[j] / (pixels/2);
|
||||
|
||||
gain[j] = (static_cast<float>(sensor.gain_white_ref) * coeff) / max[j];
|
||||
total /= width / 2;
|
||||
|
||||
gain[ch] = (static_cast<float>(sensor.gain_white_ref) * coeff) / total;
|
||||
|
||||
/* turn logical gain value into gain code, checking for overflow */
|
||||
code = static_cast<int>(283 - 208 / gain[j]);
|
||||
if (code > 255)
|
||||
code = 255;
|
||||
else if (code < 0)
|
||||
code = 0;
|
||||
dev->frontend.set_gain(j, code);
|
||||
code = static_cast<int>(283 - 208 / gain[ch]);
|
||||
code = clamp(code, 0, 255);
|
||||
dev->frontend.set_gain(ch, code);
|
||||
|
||||
DBG(DBG_proc, "%s: channel %d, max=%d, gain = %f, setting:%d\n", __func__, j, max[j], gain[j],
|
||||
dev->frontend.get_gain(j));
|
||||
DBG(DBG_proc, "%s: channel %d, total=%d, gain = %f, setting:%d\n", __func__, ch,
|
||||
static_cast<unsigned>(total), gain[ch], dev->frontend.get_gain(ch));
|
||||
}
|
||||
|
||||
if (dev->model->is_cis) {
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
*/
|
||||
|
||||
#include "genesys.h"
|
||||
#include "command_set.h"
|
||||
#include "command_set_common.h"
|
||||
|
||||
#ifndef BACKEND_GENESYS_GL846_H
|
||||
#define BACKEND_GENESYS_GL846_H
|
||||
|
@ -125,7 +125,7 @@ static Memory_layout layouts[]={
|
|||
{ nullptr, 0, 0, 0, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }
|
||||
};
|
||||
|
||||
class CommandSetGl846 : public CommandSet
|
||||
class CommandSetGl846 : public CommandSetCommon
|
||||
{
|
||||
public:
|
||||
~CommandSetGl846() override = default;
|
||||
|
@ -138,13 +138,11 @@ public:
|
|||
Genesys_Register_Set* regs, int* channels,
|
||||
int* total_size) const override;
|
||||
|
||||
void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg,
|
||||
|
@ -161,8 +159,6 @@ public:
|
|||
|
||||
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
|
||||
void search_start_position(Genesys_Device* dev) const override;
|
||||
|
||||
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
|
@ -188,9 +184,6 @@ public:
|
|||
|
||||
void eject_document(Genesys_Device* dev) const override;
|
||||
|
||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
bool forward, bool black) const override;
|
||||
|
||||
void move_to_ta(Genesys_Device* dev) const override;
|
||||
|
||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||
|
|
|
@ -238,9 +238,6 @@ gl847_init_registers (Genesys_Device * dev)
|
|||
|
||||
const auto& sensor = sanei_genesys_find_sensor_any(dev);
|
||||
sanei_genesys_set_dpihw(dev->reg, sensor, sensor.optical_res);
|
||||
|
||||
/* initalize calibration reg */
|
||||
dev->calib_reg = dev->reg;
|
||||
}
|
||||
|
||||
/**@brief send slope table for motor movement
|
||||
|
@ -257,7 +254,6 @@ static void gl847_send_slope_table(Genesys_Device* dev, int table_nr,
|
|||
{
|
||||
DBG_HELPER_ARGS(dbg, "table_nr = %d, steps = %d", table_nr, steps);
|
||||
int i;
|
||||
char msg[10000];
|
||||
|
||||
/* sanity check */
|
||||
if(table_nr<0 || table_nr>4)
|
||||
|
@ -272,16 +268,6 @@ static void gl847_send_slope_table(Genesys_Device* dev, int table_nr,
|
|||
table[i * 2 + 1] = slope_table[i] >> 8;
|
||||
}
|
||||
|
||||
if (DBG_LEVEL >= DBG_io)
|
||||
{
|
||||
std::sprintf(msg, "write slope %d (%d)=", table_nr, steps);
|
||||
for (i = 0; i < steps; i++)
|
||||
{
|
||||
std::sprintf(msg + std::strlen(msg), "%d", slope_table[i]);
|
||||
}
|
||||
DBG (DBG_io, "%s: %s\n", __func__, msg);
|
||||
}
|
||||
|
||||
if (dev->interface->is_mock()) {
|
||||
dev->interface->record_slope_table(table_nr, slope_table);
|
||||
}
|
||||
|
@ -354,7 +340,7 @@ void CommandSetGl847::set_fe(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
|||
static void gl847_init_motor_regs_scan(Genesys_Device* dev,
|
||||
const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg,
|
||||
const Motor_Profile& motor_profile,
|
||||
const MotorProfile& motor_profile,
|
||||
unsigned int scan_exposure_time,
|
||||
unsigned scan_yres,
|
||||
unsigned int scan_lines,
|
||||
|
@ -429,7 +415,7 @@ static void gl847_init_motor_regs_scan(Genesys_Device* dev,
|
|||
fast_step_type = StepType::QUARTER;
|
||||
}
|
||||
|
||||
Motor_Profile fast_motor_profile = motor_profile;
|
||||
MotorProfile fast_motor_profile = motor_profile;
|
||||
fast_motor_profile.step_type = fast_step_type;
|
||||
|
||||
auto fast_table = sanei_genesys_slope_table(dev->model->asic_type, fast_dpi,
|
||||
|
@ -585,7 +571,7 @@ static void gl847_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
|
|||
r->value |= REG_0x01_SHDAREA;
|
||||
|
||||
if (has_flag(session.params.flags, ScanFlag::DISABLE_SHADING) ||
|
||||
(dev->model->flags & GENESYS_FLAG_NO_CALIBRATION))
|
||||
has_flag(dev->model->flags, ModelFlag::NO_CALIBRATION))
|
||||
{
|
||||
r->value &= ~REG_0x01_DVDSET;
|
||||
}
|
||||
|
@ -672,7 +658,7 @@ static void gl847_init_optical_regs_scan(Genesys_Device* dev, const Genesys_Sens
|
|||
reg->set16(REG_STRPIXEL, session.pixel_startx);
|
||||
reg->set16(REG_ENDPIXEL, session.pixel_endx);
|
||||
|
||||
build_image_pipeline(dev, session);
|
||||
build_image_pipeline(dev, sensor, session);
|
||||
|
||||
/* MAXWD is expressed in 4 words unit */
|
||||
// BUG: we shouldn't multiply by channels here
|
||||
|
@ -712,9 +698,7 @@ void CommandSetGl847::init_regs_for_scan_session(Genesys_Device* dev, const Gene
|
|||
slope_dpi = slope_dpi * (1 + dummy);
|
||||
|
||||
exposure_time = sensor.exposure_lperiod;
|
||||
const auto& motor_profile = sanei_genesys_get_motor_profile(*gl847_motor_profiles,
|
||||
dev->model->motor_id,
|
||||
exposure_time);
|
||||
const auto& motor_profile = get_motor_profile(dev->motor.profiles, exposure_time, session);
|
||||
|
||||
DBG(DBG_info, "%s : exposure_time=%d pixels\n", __func__, exposure_time);
|
||||
DBG(DBG_info, "%s : scan_step_type=%d\n", __func__,
|
||||
|
@ -740,9 +724,7 @@ void CommandSetGl847::init_regs_for_scan_session(Genesys_Device* dev, const Gene
|
|||
}
|
||||
|
||||
gl847_init_motor_regs_scan(dev, sensor, reg, motor_profile, exposure_time, slope_dpi,
|
||||
dev->model->is_cis ? session.output_line_count * session.params.channels
|
||||
: session.output_line_count,
|
||||
dummy, move, mflags);
|
||||
session.optical_line_count, dummy, move, mflags);
|
||||
|
||||
dev->read_buffer.clear();
|
||||
dev->read_buffer.alloc(session.buffer_size_read);
|
||||
|
@ -761,21 +743,33 @@ ScanSession CommandSetGl847::calculate_scan_session(const Genesys_Device* dev,
|
|||
const Genesys_Sensor& sensor,
|
||||
const Genesys_Settings& settings) const
|
||||
{
|
||||
int start;
|
||||
|
||||
DBG(DBG_info, "%s ", __func__);
|
||||
debug_dump(DBG_info, settings);
|
||||
|
||||
/* start */
|
||||
start = static_cast<int>(dev->model->x_offset);
|
||||
start = static_cast<int>(start + settings.tl_x);
|
||||
start = static_cast<int>((start * sensor.optical_res) / MM_PER_INCH);
|
||||
/* Steps to move to reach scanning area:
|
||||
|
||||
- first we move to physical start of scanning either by a fixed steps amount from the
|
||||
black strip or by a fixed amount from parking position, minus the steps done during
|
||||
shading calibration.
|
||||
|
||||
- then we move by the needed offset whitin physical scanning area
|
||||
*/
|
||||
unsigned move_dpi = dev->motor.base_ydpi;
|
||||
|
||||
float move = dev->model->y_offset;
|
||||
move = move + settings.tl_y;
|
||||
move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
|
||||
move -= dev->head_pos(ScanHeadId::PRIMARY);
|
||||
|
||||
float start = dev->model->x_offset;
|
||||
start = start + dev->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 = start; // not used
|
||||
session.params.starty = 0; // not used
|
||||
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;
|
||||
|
@ -784,7 +778,8 @@ ScanSession CommandSetGl847::calculate_scan_session(const Genesys_Device* dev,
|
|||
session.params.scan_method = settings.scan_method;
|
||||
session.params.scan_mode = settings.scan_mode;
|
||||
session.params.color_filter = settings.color_filter;
|
||||
session.params.flags = ScanFlag::NONE;
|
||||
// backtracking isn't handled well, so don't enable it
|
||||
session.params.flags = ScanFlag::DISABLE_BUFFER_FULL_MOVE;
|
||||
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
|
@ -860,249 +855,71 @@ void CommandSetGl847::move_back_home(Genesys_Device* dev, bool wait_until_home)
|
|||
scanner_move_back_home(*dev, wait_until_home);
|
||||
}
|
||||
|
||||
// Automatically set top-left edge of the scan area by scanning a 200x200 pixels area at 600 dpi
|
||||
// from very top of scanner
|
||||
void CommandSetGl847::search_start_position(Genesys_Device* dev) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
int size;
|
||||
Genesys_Register_Set local_reg;
|
||||
|
||||
int pixels = 600;
|
||||
int dpi = 300;
|
||||
|
||||
local_reg = dev->reg;
|
||||
|
||||
/* sets for a 200 lines * 600 pixels */
|
||||
/* normal scan with no shading */
|
||||
|
||||
// FIXME: the current approach of doing search only for one resolution does not work on scanners
|
||||
// whith employ different sensors with potentially different settings.
|
||||
const auto& sensor = sanei_genesys_find_sensor(dev, dpi, 1, dev->model->default_method);
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = dpi;
|
||||
session.params.yres = dpi;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = 0; /*we should give a small offset here~60 steps */
|
||||
session.params.pixels = 600;
|
||||
session.params.lines = dev->model->search_lines;
|
||||
session.params.depth = 8;
|
||||
session.params.channels = 1;
|
||||
session.params.scan_method = dev->settings.scan_method;
|
||||
session.params.scan_mode = ScanColorMode::GRAY;
|
||||
session.params.color_filter = ColorFilter::GREEN;
|
||||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, sensor, &local_reg, session);
|
||||
|
||||
// send to scanner
|
||||
dev->interface->write_registers(local_reg);
|
||||
|
||||
size = pixels * dev->model->search_lines;
|
||||
|
||||
std::vector<uint8_t> data(size);
|
||||
|
||||
begin_scan(dev, sensor, &local_reg, true);
|
||||
|
||||
if (is_testing_mode()) {
|
||||
dev->interface->test_checkpoint("search_start_position");
|
||||
end_scan(dev, &local_reg, true);
|
||||
dev->reg = local_reg;
|
||||
return;
|
||||
}
|
||||
|
||||
wait_until_buffer_non_empty(dev);
|
||||
|
||||
// now we're on target, we can read data
|
||||
sanei_genesys_read_data_from_scanner(dev, data.data(), size);
|
||||
|
||||
if (DBG_LEVEL >= DBG_data) {
|
||||
sanei_genesys_write_pnm_file("gl847_search_position.pnm", data.data(), 8, 1, pixels,
|
||||
dev->model->search_lines);
|
||||
}
|
||||
|
||||
end_scan(dev, &local_reg, true);
|
||||
|
||||
/* update regs to copy ASIC internal state */
|
||||
dev->reg = local_reg;
|
||||
|
||||
// TODO: find out where sanei_genesys_search_reference_point stores information,
|
||||
// and use that correctly
|
||||
for (auto& sensor_update :
|
||||
sanei_genesys_find_sensors_all_for_write(dev, dev->model->default_method))
|
||||
{
|
||||
sanei_genesys_search_reference_point(dev, sensor_update, data.data(), 0, dpi, pixels,
|
||||
dev->model->search_lines);
|
||||
}
|
||||
}
|
||||
|
||||
// sets up register for coarse gain calibration
|
||||
// todo: check it for scanners using it
|
||||
void CommandSetGl847::init_regs_for_coarse_calibration(Genesys_Device* dev,
|
||||
const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = dev->settings.xres;
|
||||
session.params.yres = dev->settings.yres;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = 0;
|
||||
session.params.pixels = sensor.optical_res / sensor.ccd_pixels_per_system_pixel();
|
||||
session.params.lines = 20;
|
||||
session.params.depth = 16;
|
||||
session.params.channels = dev->settings.get_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 = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::SINGLE_LINE |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, sensor, ®s, session);
|
||||
|
||||
DBG(DBG_info, "%s: optical sensor res: %d dpi, actual res: %d\n", __func__,
|
||||
sensor.optical_res / sensor.ccd_pixels_per_system_pixel(), dev->settings.xres);
|
||||
|
||||
dev->interface->write_registers(regs);
|
||||
}
|
||||
|
||||
// init registers for shading calibration
|
||||
void CommandSetGl847::init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
|
||||
dev->calib_channels = 3;
|
||||
unsigned channels = 3;
|
||||
|
||||
/* initial calibration reg values */
|
||||
regs = dev->reg;
|
||||
unsigned resolution = sensor.get_register_hwdpi(dev->settings.xres);
|
||||
|
||||
dev->calib_resolution = sensor.get_register_hwdpi(dev->settings.xres);
|
||||
|
||||
const auto& calib_sensor = sanei_genesys_find_sensor(dev, dev->calib_resolution,
|
||||
dev->calib_channels,
|
||||
const auto& calib_sensor = sanei_genesys_find_sensor(dev, resolution, channels,
|
||||
dev->settings.scan_method);
|
||||
|
||||
dev->calib_total_bytes_to_read = 0;
|
||||
dev->calib_lines = dev->model->shading_lines;
|
||||
if (dev->calib_resolution == 4800) {
|
||||
dev->calib_lines *= 2;
|
||||
}
|
||||
dev->calib_pixels = (calib_sensor.sensor_pixels * dev->calib_resolution) /
|
||||
calib_sensor.optical_res;
|
||||
|
||||
DBG(DBG_io, "%s: calib_lines = %zu\n", __func__, dev->calib_lines);
|
||||
DBG(DBG_io, "%s: calib_pixels = %zu\n", __func__, dev->calib_pixels);
|
||||
unsigned calib_lines =
|
||||
static_cast<unsigned>(dev->model->y_size_calib_mm * resolution / MM_PER_INCH);
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = dev->calib_resolution;
|
||||
session.params.yres = dev->motor.base_ydpi;
|
||||
session.params.xres = resolution;
|
||||
session.params.yres = resolution;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = 20;
|
||||
session.params.pixels = dev->calib_pixels;
|
||||
session.params.lines = dev->calib_lines;
|
||||
session.params.pixels = dev->model->x_size_calib_mm * resolution / MM_PER_INCH;;
|
||||
session.params.lines = calib_lines;
|
||||
session.params.depth = 16;
|
||||
session.params.channels = dev->calib_channels;
|
||||
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 = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::DISABLE_BUFFER_FULL_MOVE |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
ScanFlag::DISABLE_BUFFER_FULL_MOVE;
|
||||
compute_session(dev, session, calib_sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, calib_sensor, ®s, session);
|
||||
|
||||
dev->interface->write_registers(regs);
|
||||
|
||||
/* we use GENESYS_FLAG_SHADING_REPARK */
|
||||
/* we use ModelFlag::SHADING_REPARK */
|
||||
dev->set_head_pos_zero(ScanHeadId::PRIMARY);
|
||||
|
||||
dev->calib_session = session;
|
||||
}
|
||||
|
||||
/** @brief set up registers for the actual scan
|
||||
*/
|
||||
void CommandSetGl847::init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const
|
||||
void CommandSetGl847::init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
float move;
|
||||
int move_dpi;
|
||||
float start;
|
||||
|
||||
debug_dump(DBG_info, dev->settings);
|
||||
auto session = calculate_scan_session(dev, sensor, dev->settings);
|
||||
|
||||
/* steps to move to reach scanning area:
|
||||
- first we move to physical start of scanning
|
||||
either by a fixed steps amount from the black strip
|
||||
or by a fixed amount from parking position,
|
||||
minus the steps done during shading calibration
|
||||
- then we move by the needed offset whitin physical
|
||||
scanning area
|
||||
/* Fast move to scan area:
|
||||
|
||||
assumption: steps are expressed at maximum motor resolution
|
||||
|
||||
we need:
|
||||
float y_offset;
|
||||
float y_size;
|
||||
float y_offset_calib;
|
||||
mm_to_steps()=motor dpi / 2.54 / 10=motor dpi / MM_PER_INCH */
|
||||
|
||||
/* if scanner uses GENESYS_FLAG_SEARCH_START y_offset is
|
||||
relative from origin, else, it is from parking position */
|
||||
|
||||
move_dpi = dev->motor.base_ydpi;
|
||||
|
||||
move = static_cast<float>(dev->model->y_offset);
|
||||
move = static_cast<float>(move + dev->settings.tl_y);
|
||||
move = static_cast<float>((move * move_dpi) / MM_PER_INCH);
|
||||
move -= dev->head_pos(ScanHeadId::PRIMARY);
|
||||
DBG(DBG_info, "%s: move=%f steps\n", __func__, move);
|
||||
|
||||
/* fast move to scan area */
|
||||
/* we don't move fast the whole distance since it would involve
|
||||
* computing acceleration/deceleration distance for scan
|
||||
* resolution. So leave a remainder for it so scan makes the final
|
||||
* move tuning */
|
||||
if (dev->settings.get_channels() * dev->settings.yres >= 600 && move > 700) {
|
||||
scanner_move(*dev, dev->model->default_method, static_cast<unsigned>(move - 500),
|
||||
We don't move fast the whole distance since it would involve computing
|
||||
acceleration/deceleration distance for scan resolution. So leave a remainder for it so
|
||||
scan makes the final move tuning
|
||||
*/
|
||||
if (dev->settings.get_channels() * dev->settings.yres >= 600 && session.params.starty > 700) {
|
||||
scanner_move(*dev, dev->model->default_method,
|
||||
static_cast<unsigned>(session.params.starty - 500),
|
||||
Direction::FORWARD);
|
||||
move=500;
|
||||
session.params.starty = 500;
|
||||
}
|
||||
|
||||
DBG(DBG_info, "%s: move=%f steps\n", __func__, move);
|
||||
DBG(DBG_info, "%s: move=%f steps\n", __func__, move);
|
||||
|
||||
/* start */
|
||||
start = static_cast<float>(dev->model->x_offset);
|
||||
start = static_cast<float>(start + dev->settings.tl_x);
|
||||
start = static_cast<float>((start * sensor.optical_res) / MM_PER_INCH);
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = dev->settings.xres;
|
||||
session.params.yres = dev->settings.yres;
|
||||
session.params.startx = static_cast<unsigned>(start);
|
||||
session.params.starty = static_cast<unsigned>(move);
|
||||
session.params.pixels = dev->settings.pixels;
|
||||
session.params.requested_pixels = dev->settings.requested_pixels;
|
||||
session.params.lines = dev->settings.lines;
|
||||
session.params.depth = dev->settings.depth;
|
||||
session.params.channels = dev->settings.get_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;
|
||||
// backtracking isn't handled well, so don't enable it
|
||||
session.params.flags = ScanFlag::DISABLE_BUFFER_FULL_MOVE;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, sensor, &dev->reg, session);
|
||||
init_regs_for_scan_session(dev, sensor, ®s, session);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1193,18 +1010,14 @@ SensorExposure CommandSetGl847::led_calibration(Genesys_Device* dev, const Genes
|
|||
Genesys_Register_Set& regs) const
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
int num_pixels;
|
||||
int total_size;
|
||||
int used_res;
|
||||
int i, j;
|
||||
int val;
|
||||
int channels;
|
||||
int i;
|
||||
int avg[3], top[3], bottom[3];
|
||||
int turn;
|
||||
uint16_t exp[3];
|
||||
float move;
|
||||
|
||||
move = static_cast<float>(dev->model->y_offset_calib_white);
|
||||
move = dev->model->y_offset_calib_white;
|
||||
move = static_cast<float>((move * (dev->motor.base_ydpi / 4)) / MM_PER_INCH);
|
||||
if (move > 20) {
|
||||
scanner_move(*dev, dev->model->default_method, static_cast<unsigned>(move),
|
||||
|
@ -1213,11 +1026,10 @@ SensorExposure CommandSetGl847::led_calibration(Genesys_Device* dev, const Genes
|
|||
DBG(DBG_io, "%s: move=%f steps\n", __func__, move);
|
||||
|
||||
/* offset calibration is always done in color mode */
|
||||
channels = 3;
|
||||
unsigned channels = 3;
|
||||
used_res = sensor.get_register_hwdpi(dev->settings.xres);
|
||||
const auto& calib_sensor = sanei_genesys_find_sensor(dev, used_res, channels,
|
||||
dev->settings.scan_method);
|
||||
num_pixels = (calib_sensor.sensor_pixels * used_res) / calib_sensor.optical_res;
|
||||
|
||||
/* initial calibration reg values */
|
||||
regs = dev->reg;
|
||||
|
@ -1227,7 +1039,7 @@ SensorExposure CommandSetGl847::led_calibration(Genesys_Device* dev, const Genes
|
|||
session.params.yres = used_res;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = 0;
|
||||
session.params.pixels = num_pixels;
|
||||
session.params.pixels = dev->model->x_size_calib_mm * used_res / MM_PER_INCH;
|
||||
session.params.lines = 1;
|
||||
session.params.depth = 16;
|
||||
session.params.channels = channels;
|
||||
|
@ -1237,14 +1049,12 @@ SensorExposure CommandSetGl847::led_calibration(Genesys_Device* dev, const Genes
|
|||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::SINGLE_LINE |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
ScanFlag::IGNORE_STAGGER_OFFSET |
|
||||
ScanFlag::IGNORE_COLOR_OFFSET;
|
||||
compute_session(dev, session, calib_sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, calib_sensor, ®s, session);
|
||||
|
||||
total_size = num_pixels * channels * (session.params.depth/8) * 1;
|
||||
std::vector<uint8_t> line(total_size);
|
||||
|
||||
// initial loop values and boundaries
|
||||
exp[0] = calib_sensor.exposure.red;
|
||||
exp[1] = calib_sensor.exposure.green;
|
||||
|
@ -1283,38 +1093,25 @@ SensorExposure CommandSetGl847::led_calibration(Genesys_Device* dev, const Genes
|
|||
return calib_sensor.exposure;
|
||||
}
|
||||
|
||||
sanei_genesys_read_data_from_scanner(dev, line.data(), total_size);
|
||||
auto image = read_unshuffled_image_from_scanner(dev, session, session.output_line_bytes);
|
||||
|
||||
// stop scanning
|
||||
scanner_stop_action(*dev);
|
||||
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
char fn[30];
|
||||
if (DBG_LEVEL >= DBG_data) {
|
||||
char fn[30];
|
||||
std::snprintf(fn, 30, "gl847_led_%02d.pnm", turn);
|
||||
sanei_genesys_write_pnm_file(fn, line.data(), session.params.depth,
|
||||
channels, num_pixels, 1);
|
||||
}
|
||||
sanei_genesys_write_pnm_file(fn, image);
|
||||
}
|
||||
|
||||
/* compute average */
|
||||
for (j = 0; j < channels; j++)
|
||||
{
|
||||
avg[j] = 0;
|
||||
for (i = 0; i < num_pixels; i++)
|
||||
{
|
||||
if (dev->model->is_cis)
|
||||
val =
|
||||
line[i * 2 + j * 2 * num_pixels + 1] * 256 +
|
||||
line[i * 2 + j * 2 * num_pixels];
|
||||
else
|
||||
val =
|
||||
line[i * 2 * channels + 2 * j + 1] * 256 +
|
||||
line[i * 2 * channels + 2 * j];
|
||||
avg[j] += val;
|
||||
}
|
||||
|
||||
avg[j] /= num_pixels;
|
||||
}
|
||||
// compute average
|
||||
for (unsigned ch = 0; ch < channels; ch++) {
|
||||
avg[ch] = 0;
|
||||
for (std::size_t x = 0; x < image.get_width(); x++) {
|
||||
avg[ch] += image.get_raw_channel(x, 0, ch);
|
||||
}
|
||||
avg[ch] /= image.get_width();
|
||||
}
|
||||
|
||||
DBG(DBG_info, "%s: average: %d,%d,%d\n", __func__, avg[0], avg[1], avg[2]);
|
||||
|
||||
|
@ -1566,203 +1363,6 @@ void CommandSetGl847::update_home_sensor_gpio(Genesys_Device& dev) const
|
|||
}
|
||||
}
|
||||
|
||||
/** @brief search for a full width black or white strip.
|
||||
* This function searches for a black or white stripe across the scanning area.
|
||||
* When searching backward, the searched area must completely be of the desired
|
||||
* color since this area will be used for calibration which scans forward.
|
||||
* @param dev scanner device
|
||||
* @param forward true if searching forward, false if searching backward
|
||||
* @param black true if searching for a black strip, false for a white strip
|
||||
*/
|
||||
void CommandSetGl847::search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor, bool forward,
|
||||
bool black) const
|
||||
{
|
||||
DBG_HELPER_ARGS(dbg, "%s %s", black ? "black" : "white", forward ? "forward" : "reverse");
|
||||
unsigned int pixels, lines, channels;
|
||||
Genesys_Register_Set local_reg;
|
||||
size_t size;
|
||||
unsigned int pass, count, found, x, y;
|
||||
char title[80];
|
||||
|
||||
set_fe(dev, sensor, AFE_SET);
|
||||
scanner_stop_action(*dev);
|
||||
|
||||
// set up for a gray scan at lowest dpi
|
||||
const auto& resolution_settings = dev->model->get_resolution_settings(dev->settings.scan_method);
|
||||
unsigned dpi = resolution_settings.get_min_resolution_x();
|
||||
channels = 1;
|
||||
/* 10 MM */
|
||||
/* lines = (10 * dpi) / MM_PER_INCH; */
|
||||
/* shading calibation is done with dev->motor.base_ydpi */
|
||||
lines = (dev->model->shading_lines * dpi) / dev->motor.base_ydpi;
|
||||
pixels = (sensor.sensor_pixels * dpi) / sensor.optical_res;
|
||||
dev->set_head_pos_zero(ScanHeadId::PRIMARY);
|
||||
|
||||
local_reg = dev->reg;
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = dpi;
|
||||
session.params.yres = dpi;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = 0;
|
||||
session.params.pixels = pixels;
|
||||
session.params.lines = lines;
|
||||
session.params.depth = 8;
|
||||
session.params.channels = channels;
|
||||
session.params.scan_method = dev->settings.scan_method;
|
||||
session.params.scan_mode = ScanColorMode::GRAY;
|
||||
session.params.color_filter = ColorFilter::RED;
|
||||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA;
|
||||
if (!forward) {
|
||||
session.params.flags |= ScanFlag::REVERSE;
|
||||
}
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
size = pixels * channels * lines * (session.params.depth / 8);
|
||||
std::vector<uint8_t> data(size);
|
||||
|
||||
init_regs_for_scan_session(dev, sensor, &local_reg, session);
|
||||
|
||||
dev->interface->write_registers(local_reg);
|
||||
|
||||
begin_scan(dev, sensor, &local_reg, true);
|
||||
|
||||
if (is_testing_mode()) {
|
||||
dev->interface->test_checkpoint("search_strip");
|
||||
scanner_stop_action(*dev);
|
||||
return;
|
||||
}
|
||||
|
||||
wait_until_buffer_non_empty(dev);
|
||||
|
||||
// now we're on target, we can read data
|
||||
sanei_genesys_read_data_from_scanner(dev, data.data(), size);
|
||||
|
||||
scanner_stop_action(*dev);
|
||||
|
||||
pass = 0;
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
std::sprintf(title, "gl847_search_strip_%s_%s%02d.pnm",
|
||||
black ? "black" : "white", forward ? "fwd" : "bwd", pass);
|
||||
sanei_genesys_write_pnm_file(title, data.data(), session.params.depth,
|
||||
channels, pixels, lines);
|
||||
}
|
||||
|
||||
/* loop until strip is found or maximum pass number done */
|
||||
found = 0;
|
||||
while (pass < 20 && !found)
|
||||
{
|
||||
dev->interface->write_registers(local_reg);
|
||||
|
||||
// now start scan
|
||||
begin_scan(dev, sensor, &local_reg, true);
|
||||
|
||||
wait_until_buffer_non_empty(dev);
|
||||
|
||||
// now we're on target, we can read data
|
||||
sanei_genesys_read_data_from_scanner(dev, data.data(), size);
|
||||
|
||||
scanner_stop_action(*dev);
|
||||
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
std::sprintf(title, "gl847_search_strip_%s_%s%02d.pnm",
|
||||
black ? "black" : "white",
|
||||
forward ? "fwd" : "bwd", static_cast<int>(pass));
|
||||
sanei_genesys_write_pnm_file(title, data.data(), session.params.depth,
|
||||
channels, pixels, lines);
|
||||
}
|
||||
|
||||
/* search data to find black strip */
|
||||
/* when searching forward, we only need one line of the searched color since we
|
||||
* will scan forward. But when doing backward search, we need all the area of the
|
||||
* same color */
|
||||
if (forward)
|
||||
{
|
||||
for (y = 0; y < lines && !found; y++)
|
||||
{
|
||||
count = 0;
|
||||
/* count of white/black pixels depending on the color searched */
|
||||
for (x = 0; x < pixels; x++)
|
||||
{
|
||||
/* when searching for black, detect white pixels */
|
||||
if (black && data[y * pixels + x] > 90)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
/* when searching for white, detect black pixels */
|
||||
if (!black && data[y * pixels + x] < 60)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* at end of line, if count >= 3%, line is not fully of the desired color
|
||||
* so we must go to next line of the buffer */
|
||||
/* count*100/pixels < 3 */
|
||||
if ((count * 100) / pixels < 3)
|
||||
{
|
||||
found = 1;
|
||||
DBG(DBG_data, "%s: strip found forward during pass %d at line %d\n", __func__,
|
||||
pass, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG(DBG_data, "%s: pixels=%d, count=%d (%d%%)\n", __func__, pixels, count,
|
||||
(100 * count) / pixels);
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* since calibration scans are done forward, we need the whole area
|
||||
to be of the required color when searching backward */
|
||||
{
|
||||
count = 0;
|
||||
for (y = 0; y < lines; y++)
|
||||
{
|
||||
/* count of white/black pixels depending on the color searched */
|
||||
for (x = 0; x < pixels; x++)
|
||||
{
|
||||
/* when searching for black, detect white pixels */
|
||||
if (black && data[y * pixels + x] > 90)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
/* when searching for white, detect black pixels */
|
||||
if (!black && data[y * pixels + x] < 60)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* at end of area, if count >= 3%, area is not fully of the desired color
|
||||
* so we must go to next buffer */
|
||||
if ((count * 100) / (pixels * lines) < 3)
|
||||
{
|
||||
found = 1;
|
||||
DBG(DBG_data, "%s: strip found backward during pass %d \n", __func__, pass);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG(DBG_data, "%s: pixels=%d, count=%d (%d%%)\n", __func__, pixels, count,
|
||||
(100 * count) / pixels);
|
||||
}
|
||||
}
|
||||
pass++;
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
DBG(DBG_info, "%s: %s strip found\n", __func__, black ? "black" : "white");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw SaneException(SANE_STATUS_UNSUPPORTED, "%s strip not found", black ? "black" : "white");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* average dark pixels of a 8 bits scan
|
||||
*/
|
||||
|
@ -1805,9 +1405,9 @@ void CommandSetGl847::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
{
|
||||
DBG_HELPER(dbg);
|
||||
unsigned channels;
|
||||
int pass = 0, avg, total_size;
|
||||
int pass = 0, avg;
|
||||
int topavg, bottomavg, lines;
|
||||
int top, bottom, black_pixels, pixels;
|
||||
int top, bottom, black_pixels;
|
||||
|
||||
// no gain nor offset for AKM AFE
|
||||
uint8_t reg04 = dev->interface->read_register(REG_0x04);
|
||||
|
@ -1817,9 +1417,8 @@ void CommandSetGl847::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
|
||||
/* offset calibration is always done in color mode */
|
||||
channels = 3;
|
||||
dev->calib_pixels = sensor.sensor_pixels;
|
||||
lines=1;
|
||||
pixels= (sensor.sensor_pixels * sensor.optical_res) / sensor.optical_res;
|
||||
unsigned pixels = dev->model->x_size_calib_mm * sensor.optical_res / MM_PER_INCH;
|
||||
black_pixels = (sensor.black_pixels * sensor.optical_res) / sensor.optical_res;
|
||||
DBG(DBG_io2, "%s: black_pixels=%d\n", __func__, black_pixels);
|
||||
|
||||
|
@ -1838,19 +1437,14 @@ void CommandSetGl847::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::SINGLE_LINE |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
ScanFlag::IGNORE_STAGGER_OFFSET |
|
||||
ScanFlag::IGNORE_COLOR_OFFSET;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
init_regs_for_scan_session(dev, sensor, ®s, session);
|
||||
|
||||
sanei_genesys_set_motor_power(regs, false);
|
||||
|
||||
/* allocate memory for scans */
|
||||
total_size = pixels * channels * lines * (session.params.depth / 8); /* colors * bytes_per_color * scan lines */
|
||||
|
||||
std::vector<uint8_t> first_line(total_size);
|
||||
std::vector<uint8_t> second_line(total_size);
|
||||
|
||||
/* init gain */
|
||||
dev->frontend.set_gain(0, 0);
|
||||
dev->frontend.set_gain(1, 0);
|
||||
|
@ -1872,16 +1466,14 @@ void CommandSetGl847::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
return;
|
||||
}
|
||||
|
||||
sanei_genesys_read_data_from_scanner(dev, first_line.data(), total_size);
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
char fn[30];
|
||||
auto first_line = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
||||
if (DBG_LEVEL >= DBG_data) {
|
||||
char fn[30];
|
||||
std::snprintf(fn, 30, "gl847_offset%03d.pnm", bottom);
|
||||
sanei_genesys_write_pnm_file(fn, first_line.data(), session.params.depth,
|
||||
channels, pixels, lines);
|
||||
}
|
||||
sanei_genesys_write_pnm_file(fn, first_line);
|
||||
}
|
||||
|
||||
bottomavg = dark_average (first_line.data(), pixels, lines, channels, black_pixels);
|
||||
bottomavg = dark_average(first_line.get_row_ptr(0), pixels, lines, channels, black_pixels);
|
||||
DBG(DBG_io2, "%s: bottom avg=%d\n", __func__, bottomavg);
|
||||
|
||||
/* now top value */
|
||||
|
@ -1893,9 +1485,9 @@ void CommandSetGl847::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
dev->interface->write_registers(regs);
|
||||
DBG(DBG_info, "%s: starting second line reading\n", __func__);
|
||||
begin_scan(dev, sensor, ®s, true);
|
||||
sanei_genesys_read_data_from_scanner(dev, second_line.data(), total_size);
|
||||
auto second_line = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
||||
|
||||
topavg = dark_average(second_line.data(), pixels, lines, channels, black_pixels);
|
||||
topavg = dark_average(second_line.get_row_ptr(0), pixels, lines, channels, black_pixels);
|
||||
DBG(DBG_io2, "%s: top avg=%d\n", __func__, topavg);
|
||||
|
||||
/* loop until acceptable level */
|
||||
|
@ -1913,17 +1505,15 @@ void CommandSetGl847::offset_calibration(Genesys_Device* dev, const Genesys_Sens
|
|||
dev->interface->write_registers(regs);
|
||||
DBG(DBG_info, "%s: starting second line reading\n", __func__);
|
||||
begin_scan(dev, sensor, ®s, true);
|
||||
sanei_genesys_read_data_from_scanner(dev, second_line.data(), total_size);
|
||||
second_line = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
||||
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
char fn[30];
|
||||
if (DBG_LEVEL >= DBG_data) {
|
||||
char fn[30];
|
||||
std::snprintf(fn, 30, "gl847_offset%03d.pnm", dev->frontend.get_offset(1));
|
||||
sanei_genesys_write_pnm_file(fn, second_line.data(), session.params.depth,
|
||||
channels, pixels, lines);
|
||||
}
|
||||
sanei_genesys_write_pnm_file(fn, second_line);
|
||||
}
|
||||
|
||||
avg = dark_average(second_line.data(), pixels, lines, channels, black_pixels);
|
||||
avg = dark_average(second_line.get_row_ptr(0), pixels, lines, channels, black_pixels);
|
||||
DBG(DBG_info, "%s: avg=%d offset=%d\n", __func__, avg, dev->frontend.get_offset(1));
|
||||
|
||||
/* compute new boundaries */
|
||||
|
@ -1948,12 +1538,8 @@ void CommandSetGl847::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
Genesys_Register_Set& regs, int dpi) const
|
||||
{
|
||||
DBG_HELPER_ARGS(dbg, "dpi = %d", dpi);
|
||||
int pixels;
|
||||
int total_size;
|
||||
int i, j, channels;
|
||||
int max[3];
|
||||
float gain[3],coeff;
|
||||
int val, code, lines;
|
||||
int code, lines;
|
||||
|
||||
// no gain nor offset for AKM AFE
|
||||
uint8_t reg04 = dev->interface->read_register(REG_0x04);
|
||||
|
@ -1962,7 +1548,7 @@ void CommandSetGl847::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
}
|
||||
|
||||
/* coarse gain calibration is always done in color mode */
|
||||
channels = 3;
|
||||
unsigned channels = 3;
|
||||
|
||||
/* follow CKSEL */
|
||||
if(dev->settings.xres<sensor.optical_res)
|
||||
|
@ -1974,14 +1560,13 @@ void CommandSetGl847::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
coeff=1.0;
|
||||
}
|
||||
lines=10;
|
||||
pixels = (sensor.sensor_pixels * sensor.optical_res) / sensor.optical_res;
|
||||
|
||||
ScanSession session;
|
||||
session.params.xres = sensor.optical_res;
|
||||
session.params.yres = sensor.optical_res;
|
||||
session.params.startx = 0;
|
||||
session.params.starty = 0;
|
||||
session.params.pixels = pixels;
|
||||
session.params.pixels = dev->model->x_size_calib_mm * sensor.optical_res / MM_PER_INCH;
|
||||
session.params.lines = lines;
|
||||
session.params.depth = 8;
|
||||
session.params.channels = channels;
|
||||
|
@ -1991,7 +1576,8 @@ void CommandSetGl847::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
session.params.flags = ScanFlag::DISABLE_SHADING |
|
||||
ScanFlag::DISABLE_GAMMA |
|
||||
ScanFlag::SINGLE_LINE |
|
||||
ScanFlag::IGNORE_LINE_DISTANCE;
|
||||
ScanFlag::IGNORE_STAGGER_OFFSET |
|
||||
ScanFlag::IGNORE_COLOR_OFFSET;
|
||||
compute_session(dev, session, sensor);
|
||||
|
||||
try {
|
||||
|
@ -2005,10 +1591,6 @@ void CommandSetGl847::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
|
||||
dev->interface->write_registers(regs);
|
||||
|
||||
total_size = pixels * channels * (16 / session.params.depth) * lines;
|
||||
|
||||
std::vector<uint8_t> line(total_size);
|
||||
|
||||
set_fe(dev, sensor, AFE_SET);
|
||||
begin_scan(dev, sensor, ®s, true);
|
||||
|
||||
|
@ -2019,41 +1601,33 @@ void CommandSetGl847::coarse_gain_calibration(Genesys_Device* dev, const Genesys
|
|||
return;
|
||||
}
|
||||
|
||||
sanei_genesys_read_data_from_scanner(dev, line.data(), total_size);
|
||||
auto image = read_unshuffled_image_from_scanner(dev, session, session.output_total_bytes);
|
||||
|
||||
if (DBG_LEVEL >= DBG_data) {
|
||||
sanei_genesys_write_pnm_file("gl847_gain.pnm", line.data(), session.params.depth,
|
||||
channels, pixels, lines);
|
||||
sanei_genesys_write_pnm_file("gl847_gain.pnm", image);
|
||||
}
|
||||
|
||||
/* average value on each channel */
|
||||
for (j = 0; j < channels; j++)
|
||||
{
|
||||
max[j] = 0;
|
||||
for (i = pixels/4; i < (pixels*3/4); i++)
|
||||
{
|
||||
if (dev->model->is_cis) {
|
||||
val = line[i + j * pixels];
|
||||
} else {
|
||||
val = line[i * channels + j];
|
||||
}
|
||||
for (unsigned ch = 0; ch < channels; ch++) {
|
||||
|
||||
max[j] += val;
|
||||
}
|
||||
max[j] = max[j] / (pixels/2);
|
||||
auto width = image.get_width();
|
||||
|
||||
gain[j] = (static_cast<float>(sensor.gain_white_ref) * coeff) / max[j];
|
||||
std::uint64_t total = 0;
|
||||
for (std::size_t x = width / 4; x < (width * 3 / 4); x++) {
|
||||
total += image.get_raw_channel(x, 0, ch);
|
||||
}
|
||||
|
||||
total /= width / 2;
|
||||
|
||||
gain[ch] = (static_cast<float>(sensor.gain_white_ref) * coeff) / total;
|
||||
|
||||
/* turn logical gain value into gain code, checking for overflow */
|
||||
code = static_cast<int>(283 - 208 / gain[j]);
|
||||
if (code > 255)
|
||||
code = 255;
|
||||
else if (code < 0)
|
||||
code = 0;
|
||||
dev->frontend.set_gain(j, code);
|
||||
code = static_cast<int>(283 - 208 / gain[ch]);
|
||||
code = clamp(code, 0, 255);
|
||||
dev->frontend.set_gain(ch, code);
|
||||
|
||||
DBG(DBG_proc, "%s: channel %d, max=%d, gain = %f, setting:%d\n", __func__, j, max[j], gain[j],
|
||||
dev->frontend.get_gain(j));
|
||||
DBG(DBG_proc, "%s: channel %d, total=%d, gain = %f, setting:%d\n", __func__, ch,
|
||||
static_cast<unsigned>(total), gain[ch], dev->frontend.get_gain(ch));
|
||||
}
|
||||
|
||||
if (dev->model->is_cis) {
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
#define BACKEND_GENESYS_GL847_H
|
||||
|
||||
#include "genesys.h"
|
||||
#include "command_set.h"
|
||||
#include "command_set_common.h"
|
||||
|
||||
namespace genesys {
|
||||
namespace gl847 {
|
||||
|
@ -113,7 +113,7 @@ static Memory_layout layouts[]={
|
|||
}
|
||||
};
|
||||
|
||||
class CommandSetGl847 : public CommandSet
|
||||
class CommandSetGl847 : public CommandSetCommon
|
||||
{
|
||||
public:
|
||||
~CommandSetGl847() override = default;
|
||||
|
@ -126,13 +126,11 @@ public:
|
|||
Genesys_Register_Set* regs, int* channels,
|
||||
int* total_size) const override;
|
||||
|
||||
void init_regs_for_coarse_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_shading(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
void init_regs_for_scan(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
void init_regs_for_scan_session(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set* reg,
|
||||
|
@ -149,8 +147,6 @@ public:
|
|||
|
||||
void send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& sensor) const override;
|
||||
|
||||
void search_start_position(Genesys_Device* dev) const override;
|
||||
|
||||
void offset_calibration(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
Genesys_Register_Set& regs) const override;
|
||||
|
||||
|
@ -176,9 +172,6 @@ public:
|
|||
|
||||
void eject_document(Genesys_Device* dev) const override;
|
||||
|
||||
void search_strip(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
bool forward, bool black) const override;
|
||||
|
||||
void move_to_ta(Genesys_Device* dev) const override;
|
||||
|
||||
void send_shading_data(Genesys_Device* dev, const Genesys_Sensor& sensor, uint8_t* data,
|
||||
|
|
|
@ -89,47 +89,11 @@ bool ImageBuffer::get_data(std::size_t size, std::uint8_t* out_data)
|
|||
return got_data;
|
||||
}
|
||||
|
||||
void FakeBufferModel::push_step(std::size_t buffer_size, std::size_t row_bytes)
|
||||
{
|
||||
sizes_.push_back(buffer_size);
|
||||
available_sizes_.push_back(0);
|
||||
row_bytes_.push_back(row_bytes);
|
||||
}
|
||||
|
||||
std::size_t FakeBufferModel::available_space() const
|
||||
{
|
||||
if (sizes_.empty())
|
||||
throw SaneException("Model has not been setup");
|
||||
return sizes_.front() - available_sizes_.front();
|
||||
}
|
||||
|
||||
void FakeBufferModel::simulate_read(std::size_t size)
|
||||
{
|
||||
if (sizes_.empty()) {
|
||||
throw SaneException("Model has not been setup");
|
||||
}
|
||||
if (available_space() < size) {
|
||||
throw SaneException("Attempted to simulate read of too much memory");
|
||||
}
|
||||
|
||||
available_sizes_.front() += size;
|
||||
|
||||
for (unsigned i = 1; i < sizes_.size(); ++i) {
|
||||
auto avail_src = available_sizes_[i - 1];
|
||||
auto avail_dst = sizes_[i] - available_sizes_[i];
|
||||
|
||||
auto avail = (std::min(avail_src, avail_dst) / row_bytes_[i]) * row_bytes_[i];
|
||||
available_sizes_[i - 1] -= avail;
|
||||
available_sizes_[i] += avail;
|
||||
}
|
||||
available_sizes_.back() = 0;
|
||||
}
|
||||
|
||||
ImageBufferGenesysUsb::ImageBufferGenesysUsb(std::size_t total_size,
|
||||
const FakeBufferModel& buffer_model,
|
||||
std::size_t buffer_size,
|
||||
ProducerCallback producer) :
|
||||
remaining_size_{total_size},
|
||||
buffer_model_{buffer_model},
|
||||
buffer_size_{buffer_size},
|
||||
producer_{producer}
|
||||
{}
|
||||
|
||||
|
@ -179,7 +143,7 @@ bool ImageBufferGenesysUsb::get_data(std::size_t size, std::uint8_t* out_data)
|
|||
|
||||
std::size_t ImageBufferGenesysUsb::get_read_size()
|
||||
{
|
||||
std::size_t size = buffer_model_.available_space();
|
||||
std::size_t size = buffer_size_;
|
||||
|
||||
// never read an odd number. exception: last read
|
||||
// the chip internal counter does not count half words.
|
||||
|
@ -195,8 +159,6 @@ std::size_t ImageBufferGenesysUsb::get_read_size()
|
|||
size &= ~0xff;
|
||||
}
|
||||
|
||||
buffer_model_.simulate_read(size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,23 +73,6 @@ private:
|
|||
std::vector<std::uint8_t> buffer_;
|
||||
};
|
||||
|
||||
class FakeBufferModel
|
||||
{
|
||||
public:
|
||||
FakeBufferModel() {}
|
||||
|
||||
void push_step(std::size_t buffer_size, std::size_t row_bytes);
|
||||
|
||||
std::size_t available_space() const;
|
||||
|
||||
void simulate_read(std::size_t size);
|
||||
|
||||
private:
|
||||
std::vector<std::size_t> sizes_;
|
||||
std::vector<std::size_t> available_sizes_;
|
||||
std::vector<std::size_t> row_bytes_;
|
||||
};
|
||||
|
||||
// This class is similar to ImageBuffer, but preserves historical peculiarities of buffer handling
|
||||
// in the backend to preserve exact behavior
|
||||
class ImageBufferGenesysUsb
|
||||
|
@ -98,7 +81,7 @@ public:
|
|||
using ProducerCallback = std::function<void(std::size_t size, std::uint8_t* out_data)>;
|
||||
|
||||
ImageBufferGenesysUsb() {}
|
||||
ImageBufferGenesysUsb(std::size_t total_size, const FakeBufferModel& buffer_model,
|
||||
ImageBufferGenesysUsb(std::size_t total_size, std::size_t buffer_size,
|
||||
ProducerCallback producer);
|
||||
|
||||
std::size_t remaining_size() const { return remaining_size_; }
|
||||
|
@ -115,12 +98,12 @@ private:
|
|||
|
||||
std::size_t remaining_size_ = 0;
|
||||
|
||||
std::size_t buffer_size_ = 0;
|
||||
|
||||
std::size_t buffer_offset_ = 0;
|
||||
std::size_t buffer_end_ = 0;
|
||||
std::vector<std::uint8_t> buffer_;
|
||||
|
||||
FakeBufferModel buffer_model_;
|
||||
|
||||
ProducerCallback producer_;
|
||||
};
|
||||
|
||||
|
|
|
@ -109,11 +109,11 @@ bool ImagePipelineNodeBufferedCallableSource::get_next_row_data(std::uint8_t* ou
|
|||
|
||||
ImagePipelineNodeBufferedGenesysUsb::ImagePipelineNodeBufferedGenesysUsb(
|
||||
std::size_t width, std::size_t height, PixelFormat format, std::size_t total_size,
|
||||
const FakeBufferModel& buffer_model, ProducerCallback producer) :
|
||||
std::size_t buffer_size, ProducerCallback producer) :
|
||||
width_{width},
|
||||
height_{height},
|
||||
format_{format},
|
||||
buffer_{total_size, buffer_model, producer}
|
||||
buffer_{total_size, buffer_size, producer}
|
||||
{
|
||||
set_remaining_bytes(total_size);
|
||||
}
|
||||
|
@ -666,16 +666,21 @@ bool ImagePipelineNodeExtract::get_next_row_data(std::uint8_t* out_data)
|
|||
|
||||
ImagePipelineNodeCalibrate::ImagePipelineNodeCalibrate(ImagePipelineNode& source,
|
||||
const std::vector<std::uint16_t>& bottom,
|
||||
const std::vector<std::uint16_t>& top) :
|
||||
const std::vector<std::uint16_t>& top,
|
||||
std::size_t x_start) :
|
||||
source_{source}
|
||||
{
|
||||
auto size = std::min(bottom.size(), top.size());
|
||||
std::size_t size = 0;
|
||||
if (bottom.size() >= x_start && top.size() >= x_start) {
|
||||
size = std::min(bottom.size() - x_start, top.size() - x_start);
|
||||
}
|
||||
|
||||
offset_.reserve(size);
|
||||
multiplier_.reserve(size);
|
||||
|
||||
for (std::size_t i = 0; i < size; ++i) {
|
||||
offset_.push_back(bottom[i] / 65535.0f);
|
||||
multiplier_.push_back(65535.0f / (top[i] - bottom[i]));
|
||||
offset_.push_back(bottom[i + x_start] / 65535.0f);
|
||||
multiplier_.push_back(65535.0f / (top[i + x_start] - bottom[i + x_start]));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -157,8 +157,7 @@ public:
|
|||
|
||||
ImagePipelineNodeBufferedGenesysUsb(std::size_t width, std::size_t height,
|
||||
PixelFormat format, std::size_t total_size,
|
||||
const FakeBufferModel& buffer_model,
|
||||
ProducerCallback producer);
|
||||
std::size_t buffer_size, ProducerCallback producer);
|
||||
|
||||
std::size_t get_width() const override { return width_; }
|
||||
std::size_t get_height() const override { return height_; }
|
||||
|
@ -476,7 +475,7 @@ class ImagePipelineNodeCalibrate : public ImagePipelineNode
|
|||
public:
|
||||
|
||||
ImagePipelineNodeCalibrate(ImagePipelineNode& source, const std::vector<std::uint16_t>& bottom,
|
||||
const std::vector<std::uint16_t>& top);
|
||||
const std::vector<std::uint16_t>& top, std::size_t x_start);
|
||||
|
||||
std::size_t get_width() const override { return source_.get_width(); }
|
||||
std::size_t get_height() const override { return source_.get_height(); }
|
||||
|
|
|
@ -516,7 +516,7 @@ Image read_unshuffled_image_from_scanner(Genesys_Device* dev, const ScanSession&
|
|||
dev->model->line_mode_color_order);
|
||||
|
||||
auto width = get_pixels_from_row_bytes(format, session.output_line_bytes_raw);
|
||||
auto height = session.output_line_count * (dev->model->is_cis ? session.params.channels : 1);
|
||||
auto height = session.optical_line_count;
|
||||
|
||||
Image image(width, height, format);
|
||||
|
||||
|
@ -534,26 +534,33 @@ Image read_unshuffled_image_from_scanner(Genesys_Device* dev, const ScanSession&
|
|||
ImagePipelineStack pipeline;
|
||||
pipeline.push_first_node<ImagePipelineNodeImageSource>(image);
|
||||
|
||||
if ((dev->model->flags & GENESYS_FLAG_16BIT_DATA_INVERTED) && session.params.depth == 16) {
|
||||
dev->pipeline.push_node<ImagePipelineNodeSwap16BitEndian>();
|
||||
if (session.segment_count > 1) {
|
||||
auto output_width = session.output_segment_pixel_group_count * session.segment_count;
|
||||
pipeline.push_node<ImagePipelineNodeDesegment>(output_width, dev->segment_order,
|
||||
session.conseq_pixel_dist,
|
||||
1, 1);
|
||||
}
|
||||
|
||||
if (has_flag(dev->model->flags, ModelFlag::INVERTED_16BIT_DATA) && session.params.depth == 16) {
|
||||
pipeline.push_node<ImagePipelineNodeSwap16BitEndian>();
|
||||
}
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
if (depth == 16) {
|
||||
dev->pipeline.push_node<ImagePipelineNodeSwap16BitEndian>();
|
||||
if (session.params.depth == 16) {
|
||||
pipeline.push_node<ImagePipelineNodeSwap16BitEndian>();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dev->model->is_cis && session.params.channels == 3) {
|
||||
dev->pipeline.push_node<ImagePipelineNodeMergeMonoLines>(dev->model->line_mode_color_order);
|
||||
pipeline.push_node<ImagePipelineNodeMergeMonoLines>(dev->model->line_mode_color_order);
|
||||
}
|
||||
|
||||
if (dev->pipeline.get_output_format() == PixelFormat::BGR888) {
|
||||
dev->pipeline.push_node<ImagePipelineNodeFormatConvert>(PixelFormat::RGB888);
|
||||
if (pipeline.get_output_format() == PixelFormat::BGR888) {
|
||||
pipeline.push_node<ImagePipelineNodeFormatConvert>(PixelFormat::RGB888);
|
||||
}
|
||||
|
||||
if (dev->pipeline.get_output_format() == PixelFormat::BGR161616) {
|
||||
dev->pipeline.push_node<ImagePipelineNodeFormatConvert>(PixelFormat::RGB161616);
|
||||
if (pipeline.get_output_format() == PixelFormat::BGR161616) {
|
||||
pipeline.push_node<ImagePipelineNodeFormatConvert>(PixelFormat::RGB161616);
|
||||
}
|
||||
|
||||
return pipeline.get_image();
|
||||
|
@ -615,20 +622,9 @@ void sanei_genesys_set_lamp_power(Genesys_Device* dev, const Genesys_Sensor& sen
|
|||
regs.find_reg(0x03).value &= ~REG_0x03_LAMPPWR;
|
||||
|
||||
if (dev->model->asic_type == AsicType::GL841) {
|
||||
regs_set_exposure(dev->model->asic_type, regs, {0x0101, 0x0101, 0x0101});
|
||||
regs_set_exposure(dev->model->asic_type, regs, sanei_genesys_fixup_exposure({0, 0, 0}));
|
||||
regs.set8(0x19, 0xff);
|
||||
}
|
||||
|
||||
if (dev->model->asic_type == AsicType::GL843) {
|
||||
if (dev->model->model_id == ModelId::PANASONIC_KV_SS080 ||
|
||||
dev->model->model_id == ModelId::HP_SCANJET_4850C ||
|
||||
dev->model->model_id == ModelId::HP_SCANJET_G4010 ||
|
||||
dev->model->model_id == ModelId::HP_SCANJET_G4050)
|
||||
{
|
||||
// BUG: datasheet says we shouldn't set exposure to zero
|
||||
regs_set_exposure(dev->model->asic_type, regs, {0, 0, 0});
|
||||
}
|
||||
}
|
||||
}
|
||||
regs.state.is_lamp_on = set;
|
||||
}
|
||||
|
@ -794,70 +790,9 @@ static unsigned align_int_up(unsigned num, unsigned alignment)
|
|||
return num;
|
||||
}
|
||||
|
||||
void compute_session_buffer_sizes(AsicType asic, ScanSession& s)
|
||||
std::size_t compute_session_buffer_sizes(const ScanSession& s)
|
||||
{
|
||||
size_t line_bytes = s.output_line_bytes;
|
||||
size_t line_bytes_stagger = s.output_line_bytes;
|
||||
|
||||
if (asic != AsicType::GL646) {
|
||||
// BUG: this is historical artifact and should be removed. Note that buffer sizes affect
|
||||
// how often we request the scanner for data and thus change the USB traffic.
|
||||
line_bytes_stagger =
|
||||
multiply_by_depth_ceil(s.optical_pixels, s.params.depth) * s.params.channels;
|
||||
}
|
||||
|
||||
struct BufferConfig {
|
||||
size_t* result_size = nullptr;
|
||||
size_t lines = 0;
|
||||
size_t lines_mult = 0;
|
||||
size_t max_size = 0; // does not apply if 0
|
||||
size_t stagger_lines = 0;
|
||||
|
||||
BufferConfig() = default;
|
||||
BufferConfig(std::size_t* rs, std::size_t l, std::size_t lm, std::size_t ms,
|
||||
std::size_t sl) :
|
||||
result_size{rs},
|
||||
lines{l},
|
||||
lines_mult{lm},
|
||||
max_size{ms},
|
||||
stagger_lines{sl}
|
||||
{}
|
||||
};
|
||||
|
||||
std::array<BufferConfig, 4> configs;
|
||||
if (asic == AsicType::GL124 || asic == AsicType::GL843) {
|
||||
configs = { {
|
||||
{ &s.buffer_size_read, 32, 1, 0, s.max_color_shift_lines + s.num_staggered_lines },
|
||||
{ &s.buffer_size_lines, 32, 1, 0, s.max_color_shift_lines + s.num_staggered_lines },
|
||||
{ &s.buffer_size_shrink, 16, 1, 0, 0 },
|
||||
{ &s.buffer_size_out, 8, 1, 0, 0 },
|
||||
} };
|
||||
} else if (asic == AsicType::GL841) {
|
||||
size_t max_buf = sanei_genesys_get_bulk_max_size(asic);
|
||||
configs = { {
|
||||
{ &s.buffer_size_read, 8, 2, max_buf, s.max_color_shift_lines + s.num_staggered_lines },
|
||||
{ &s.buffer_size_lines, 8, 2, max_buf, s.max_color_shift_lines + s.num_staggered_lines },
|
||||
{ &s.buffer_size_shrink, 8, 1, max_buf, 0 },
|
||||
{ &s.buffer_size_out, 8, 1, 0, 0 },
|
||||
} };
|
||||
} else {
|
||||
configs = { {
|
||||
{ &s.buffer_size_read, 16, 1, 0, s.max_color_shift_lines + s.num_staggered_lines },
|
||||
{ &s.buffer_size_lines, 16, 1, 0, s.max_color_shift_lines + s.num_staggered_lines },
|
||||
{ &s.buffer_size_shrink, 8, 1, 0, 0 },
|
||||
{ &s.buffer_size_out, 8, 1, 0, 0 },
|
||||
} };
|
||||
}
|
||||
|
||||
for (BufferConfig& config : configs) {
|
||||
size_t buf_size = line_bytes * config.lines;
|
||||
if (config.max_size > 0 && buf_size > config.max_size) {
|
||||
buf_size = (config.max_size / line_bytes) * line_bytes;
|
||||
}
|
||||
buf_size *= config.lines_mult;
|
||||
buf_size += line_bytes_stagger * config.stagger_lines;
|
||||
*config.result_size = buf_size;
|
||||
}
|
||||
return s.output_line_bytes * (32 + s.max_color_shift_lines + s.num_staggered_lines);
|
||||
}
|
||||
|
||||
void compute_session_pipeline(const Genesys_Device* dev, ScanSession& s)
|
||||
|
@ -900,7 +835,7 @@ void compute_session_pixel_offsets(const Genesys_Device* dev, ScanSession& s,
|
|||
if (has_flag(s.params.flags, ScanFlag::USE_XCORRECTION) && sensor.ccd_start_xoffset > 0) {
|
||||
s.pixel_startx = sensor.ccd_start_xoffset;
|
||||
}
|
||||
s.pixel_startx += s.params.startx;
|
||||
s.pixel_startx += s.params.startx * sensor.optical_res / s.params.xres;
|
||||
|
||||
if (sensor.stagger_config.stagger_at_resolution(s.params.xres, s.params.yres) > 0) {
|
||||
s.pixel_startx |= 1;
|
||||
|
@ -912,7 +847,9 @@ void compute_session_pixel_offsets(const Genesys_Device* dev, ScanSession& s,
|
|||
s.pixel_endx /= sensor.ccd_pixels_per_system_pixel() * s.ccd_size_divisor;
|
||||
|
||||
} else if (dev->model->asic_type == AsicType::GL841) {
|
||||
s.pixel_startx = ((sensor.ccd_start_xoffset + s.params.startx) * s.optical_resolution)
|
||||
unsigned startx = s.params.startx * sensor.optical_res / s.params.xres;
|
||||
|
||||
s.pixel_startx = ((sensor.ccd_start_xoffset + startx) * s.optical_resolution)
|
||||
/ sensor.optical_res;
|
||||
|
||||
s.pixel_startx += sensor.dummy_pixel + 1;
|
||||
|
@ -937,15 +874,22 @@ void compute_session_pixel_offsets(const Genesys_Device* dev, ScanSession& s,
|
|||
s.pixel_endx = s.pixel_startx + s.optical_pixels;
|
||||
|
||||
} else if (dev->model->asic_type == AsicType::GL843) {
|
||||
unsigned startx = s.params.startx * sensor.optical_res / s.params.xres;
|
||||
|
||||
s.pixel_startx = (s.params.startx + sensor.dummy_pixel) / ccd_pixels_per_system_pixel;
|
||||
s.pixel_startx = (startx + sensor.dummy_pixel) / ccd_pixels_per_system_pixel;
|
||||
s.pixel_endx = s.pixel_startx + s.optical_pixels / ccd_pixels_per_system_pixel;
|
||||
|
||||
s.pixel_startx /= s.hwdpi_divisor;
|
||||
s.pixel_endx /= s.hwdpi_divisor;
|
||||
|
||||
// in case of stagger we have to start at an odd coordinate
|
||||
bool stagger_starts_even = dev->model->model_id == ModelId::CANON_8400F;
|
||||
bool stagger_starts_even = false;
|
||||
if (dev->model->model_id == ModelId::CANON_4400F ||
|
||||
dev->model->model_id == ModelId::CANON_8400F)
|
||||
{
|
||||
stagger_starts_even = true;
|
||||
}
|
||||
|
||||
if (s.num_staggered_lines > 0) {
|
||||
if (!stagger_starts_even && (s.pixel_startx & 1) == 0) {
|
||||
s.pixel_startx++;
|
||||
|
@ -960,7 +904,9 @@ void compute_session_pixel_offsets(const Genesys_Device* dev, ScanSession& s,
|
|||
dev->model->asic_type == AsicType::GL846 ||
|
||||
dev->model->asic_type == AsicType::GL847)
|
||||
{
|
||||
s.pixel_startx = s.params.startx;
|
||||
unsigned startx = s.params.startx * sensor.optical_res / s.params.xres;
|
||||
|
||||
s.pixel_startx = startx;
|
||||
|
||||
if (s.num_staggered_lines > 0) {
|
||||
s.pixel_startx |= 1;
|
||||
|
@ -973,7 +919,9 @@ void compute_session_pixel_offsets(const Genesys_Device* dev, ScanSession& s,
|
|||
s.pixel_endx /= s.hwdpi_divisor * s.segment_count * ccd_pixels_per_system_pixel;
|
||||
|
||||
} else if (dev->model->asic_type == AsicType::GL124) {
|
||||
s.pixel_startx = s.params.startx;
|
||||
unsigned startx = s.params.startx * sensor.optical_res / s.params.xres;
|
||||
|
||||
s.pixel_startx = startx;
|
||||
|
||||
if (s.num_staggered_lines > 0) {
|
||||
s.pixel_startx |= 1;
|
||||
|
@ -1067,9 +1015,8 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se
|
|||
// to retrieve from the chip
|
||||
s.output_pixels = (s.optical_pixels * s.output_resolution) / s.optical_resolution;
|
||||
|
||||
// Note: staggering is not applied for calibration. Staggering starts at 2400 dpi
|
||||
s.num_staggered_lines = 0;
|
||||
if (!has_flag(s.params.flags, ScanFlag::IGNORE_LINE_DISTANCE))
|
||||
if (!has_flag(s.params.flags, ScanFlag::IGNORE_STAGGER_OFFSET))
|
||||
{
|
||||
s.num_staggered_lines = sensor.stagger_config.stagger_at_resolution(s.params.xres,
|
||||
s.params.yres);
|
||||
|
@ -1091,12 +1038,14 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se
|
|||
s.color_shift_lines_b = (s.color_shift_lines_b * s.params.yres) / dev->motor.base_ydpi;
|
||||
|
||||
s.max_color_shift_lines = 0;
|
||||
if (s.params.channels > 1 && !has_flag(s.params.flags, ScanFlag::IGNORE_LINE_DISTANCE)) {
|
||||
if (s.params.channels > 1 && !has_flag(s.params.flags, ScanFlag::IGNORE_COLOR_OFFSET)) {
|
||||
s.max_color_shift_lines = std::max(s.color_shift_lines_r, std::max(s.color_shift_lines_g,
|
||||
s.color_shift_lines_b));
|
||||
}
|
||||
|
||||
s.output_line_count = s.params.lines + s.max_color_shift_lines + s.num_staggered_lines;
|
||||
s.optical_line_count = dev->model->is_cis ? s.output_line_count * s.params.channels
|
||||
: s.output_line_count;
|
||||
|
||||
s.output_channel_bytes = multiply_by_depth_ceil(s.output_pixels, s.params.depth);
|
||||
s.output_line_bytes = s.output_channel_bytes * s.params.channels;
|
||||
|
@ -1150,16 +1099,15 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se
|
|||
if (dev->model->asic_type == AsicType::GL124 ||
|
||||
dev->model->asic_type == AsicType::GL843)
|
||||
{
|
||||
s.output_segment_pixel_group_count = multiply_by_depth_ceil(
|
||||
s.output_pixels / s.ccd_size_divisor / s.segment_count, s.params.depth);
|
||||
s.output_segment_pixel_group_count = s.output_pixels /
|
||||
(s.ccd_size_divisor * s.segment_count);
|
||||
}
|
||||
if (dev->model->asic_type == AsicType::GL845 ||
|
||||
dev->model->asic_type == AsicType::GL846 ||
|
||||
dev->model->asic_type == AsicType::GL847)
|
||||
{
|
||||
s.output_segment_pixel_group_count = multiply_by_depth_ceil(
|
||||
s.optical_pixels / (s.hwdpi_divisor * s.segment_count * ccd_pixels_per_system_pixel),
|
||||
s.params.depth);
|
||||
s.output_segment_pixel_group_count = s.optical_pixels /
|
||||
(s.hwdpi_divisor * s.segment_count * ccd_pixels_per_system_pixel);
|
||||
}
|
||||
|
||||
s.output_line_bytes_requested = multiply_by_depth_ceil(
|
||||
|
@ -1168,7 +1116,7 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se
|
|||
s.output_total_bytes_raw = s.output_line_bytes_raw * s.output_line_count;
|
||||
s.output_total_bytes = s.output_line_bytes * s.output_line_count;
|
||||
|
||||
compute_session_buffer_sizes(dev->model->asic_type, s);
|
||||
s.buffer_size_read = compute_session_buffer_sizes(s);
|
||||
compute_session_pipeline(dev, s);
|
||||
compute_session_pixel_offsets(dev, s, sensor);
|
||||
|
||||
|
@ -1179,6 +1127,8 @@ void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Se
|
|||
s.enable_ledadd = (s.params.channels == 1 && dev->model->is_cis && dev->settings.true_gray);
|
||||
}
|
||||
|
||||
s.use_host_side_calib = sensor.use_host_side_calib;
|
||||
|
||||
if (dev->model->asic_type == AsicType::GL841 ||
|
||||
dev->model->asic_type == AsicType::GL843)
|
||||
{
|
||||
|
@ -1219,25 +1169,8 @@ static std::size_t get_usb_buffer_read_size(AsicType asic, const ScanSession& se
|
|||
}
|
||||
}
|
||||
|
||||
static FakeBufferModel get_fake_usb_buffer_model(const ScanSession& session)
|
||||
{
|
||||
FakeBufferModel model;
|
||||
model.push_step(session.buffer_size_read, 1);
|
||||
|
||||
if (session.pipeline_needs_reorder) {
|
||||
model.push_step(session.buffer_size_lines, session.output_line_bytes);
|
||||
}
|
||||
if (session.pipeline_needs_ccd) {
|
||||
model.push_step(session.buffer_size_shrink, session.output_line_bytes);
|
||||
}
|
||||
if (session.pipeline_needs_shrink) {
|
||||
model.push_step(session.buffer_size_out, session.output_line_bytes);
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
void build_image_pipeline(Genesys_Device* dev, const ScanSession& session)
|
||||
void build_image_pipeline(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
const ScanSession& session)
|
||||
{
|
||||
static unsigned s_pipeline_index = 0;
|
||||
|
||||
|
@ -1255,7 +1188,7 @@ void build_image_pipeline(Genesys_Device* dev, const ScanSession& session)
|
|||
return true;
|
||||
};
|
||||
|
||||
auto lines = session.output_line_count * (dev->model->is_cis ? session.params.channels : 1);
|
||||
auto lines = session.optical_line_count;
|
||||
|
||||
dev->pipeline.clear();
|
||||
|
||||
|
@ -1281,7 +1214,7 @@ void build_image_pipeline(Genesys_Device* dev, const ScanSession& session)
|
|||
|
||||
dev->pipeline.push_first_node<ImagePipelineNodeBufferedGenesysUsb>(
|
||||
width, lines, format, read_bytes_left_after_deseg,
|
||||
get_fake_usb_buffer_model(session), read_data_from_usb);
|
||||
session.buffer_size_read, read_data_from_usb);
|
||||
}
|
||||
|
||||
if (DBG_LEVEL >= DBG_io2) {
|
||||
|
@ -1290,7 +1223,7 @@ void build_image_pipeline(Genesys_Device* dev, const ScanSession& session)
|
|||
"_0_before_swap.pnm");
|
||||
}
|
||||
|
||||
if ((dev->model->flags & GENESYS_FLAG_16BIT_DATA_INVERTED) && depth == 16) {
|
||||
if (has_flag(dev->model->flags, ModelFlag::INVERTED_16BIT_DATA) && depth == 16) {
|
||||
dev->pipeline.push_node<ImagePipelineNodeSwap16BitEndian>();
|
||||
}
|
||||
|
||||
|
@ -1342,11 +1275,19 @@ void build_image_pipeline(Genesys_Device* dev, const ScanSession& session)
|
|||
"_3_after_stagger.pnm");
|
||||
}
|
||||
|
||||
if ((dev->model->flags & GENESYS_FLAG_CALIBRATION_HOST_SIDE) &&
|
||||
!(dev->model->flags & GENESYS_FLAG_NO_CALIBRATION))
|
||||
if (session.use_host_side_calib &&
|
||||
!has_flag(dev->model->flags, ModelFlag::NO_CALIBRATION) &&
|
||||
!has_flag(session.params.flags, ScanFlag::DISABLE_SHADING))
|
||||
{
|
||||
unsigned pixel_shift = session.params.startx;
|
||||
if (dev->model->model_id == ModelId::CANON_4400F) {
|
||||
pixel_shift =
|
||||
session.params.startx * sensor.optical_res / dev->calib_session.params.xres;
|
||||
}
|
||||
dev->pipeline.push_node<ImagePipelineNodeCalibrate>(dev->dark_average_data,
|
||||
dev->white_average_data);
|
||||
dev->white_average_data,
|
||||
pixel_shift *
|
||||
dev->calib_session.params.channels);
|
||||
|
||||
if (DBG_LEVEL >= DBG_io2) {
|
||||
dev->pipeline.push_node<ImagePipelineNodeDebug>("gl_pipeline_" +
|
||||
|
@ -1486,8 +1427,7 @@ void sanei_genesys_asic_init(Genesys_Device* dev, bool /*max_regs*/)
|
|||
|
||||
dev->settings.color_filter = ColorFilter::RED;
|
||||
|
||||
/* duplicate initial values into calibration registers */
|
||||
dev->calib_reg = dev->reg;
|
||||
dev->initial_regs = dev->reg;
|
||||
|
||||
const auto& sensor = sanei_genesys_find_sensor_any(dev);
|
||||
|
||||
|
@ -1497,8 +1437,15 @@ void sanei_genesys_asic_init(Genesys_Device* dev, bool /*max_regs*/)
|
|||
dev->already_initialized = true;
|
||||
|
||||
// Move to home if needed
|
||||
if (dev->model->model_id == ModelId::CANON_8600F) {
|
||||
if (!dev->cmd_set->is_head_home(*dev, ScanHeadId::SECONDARY)) {
|
||||
dev->set_head_pos_unknown(ScanHeadId::SECONDARY);
|
||||
}
|
||||
if (!dev->cmd_set->is_head_home(*dev, ScanHeadId::PRIMARY)) {
|
||||
dev->set_head_pos_unknown(ScanHeadId::SECONDARY);
|
||||
}
|
||||
}
|
||||
dev->cmd_set->move_back_home(dev, true);
|
||||
dev->set_head_pos_zero(ScanHeadId::PRIMARY);
|
||||
|
||||
// Set powersaving (default = 15 minutes)
|
||||
dev->cmd_set->set_powersaving(dev, 15);
|
||||
|
@ -1706,63 +1653,61 @@ void sanei_genesys_wait_for_home(Genesys_Device* dev)
|
|||
}
|
||||
}
|
||||
|
||||
/** @brief motor profile
|
||||
* search for the database of motor profiles and get the best one. Each
|
||||
* profile is at full step and at a reference exposure. Use first entry
|
||||
* by default.
|
||||
* @param motors motor profile database
|
||||
* @param motor_type motor id
|
||||
* @param exposure exposure time
|
||||
* @return a pointer to a Motor_Profile struct
|
||||
*/
|
||||
const Motor_Profile& sanei_genesys_get_motor_profile(const std::vector<Motor_Profile>& motors,
|
||||
MotorId motor_id, int exposure)
|
||||
const MotorProfile* get_motor_profile_ptr(const std::vector<MotorProfile>& profiles,
|
||||
unsigned exposure,
|
||||
const ScanSession& session)
|
||||
{
|
||||
int idx;
|
||||
int best_i = -1;
|
||||
|
||||
idx=-1;
|
||||
for (std::size_t i = 0; i < motors.size(); ++i) {
|
||||
// exact match
|
||||
if (motors[i].motor_id == motor_id && motors[i].exposure==exposure) {
|
||||
return motors[i];
|
||||
for (unsigned i = 0; i < profiles.size(); ++i) {
|
||||
const auto& profile = profiles[i];
|
||||
|
||||
if (!profile.resolutions.matches(session.params.yres)) {
|
||||
continue;
|
||||
}
|
||||
if (!profile.scan_methods.matches(session.params.scan_method)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// closest match
|
||||
if (motors[i].motor_id == motor_id) {
|
||||
/* if profile exposure is higher than the required one,
|
||||
* the entry is a candidate for the closest match */
|
||||
if (motors[i].exposure == 0 || motors[i].exposure >= exposure)
|
||||
{
|
||||
if(idx<0)
|
||||
{
|
||||
/* no match found yet */
|
||||
idx=i;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* test for better match */
|
||||
if(motors[i].exposure<motors[idx].exposure)
|
||||
{
|
||||
idx=i;
|
||||
}
|
||||
if (profile.max_exposure == exposure) {
|
||||
return &profile;
|
||||
}
|
||||
|
||||
if (profile.max_exposure == 0 || profile.max_exposure >= exposure) {
|
||||
if (best_i < 0) {
|
||||
// no match found yet
|
||||
best_i = i;
|
||||
} else {
|
||||
// test for better match
|
||||
if (profiles[i].max_exposure < profiles[best_i].max_exposure) {
|
||||
best_i = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* default fallback */
|
||||
if(idx<0)
|
||||
{
|
||||
DBG (DBG_warn,"%s: using default motor profile\n",__func__);
|
||||
idx=0;
|
||||
if (best_i < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return motors[idx];
|
||||
return &profiles[best_i];
|
||||
}
|
||||
|
||||
const MotorProfile& get_motor_profile(const std::vector<MotorProfile>& profiles,
|
||||
unsigned exposure,
|
||||
const ScanSession& session)
|
||||
{
|
||||
const auto* profile = get_motor_profile_ptr(profiles, exposure, session);
|
||||
if (profile == nullptr) {
|
||||
throw SaneException("Motor slope is not configured");
|
||||
}
|
||||
|
||||
return *profile;
|
||||
}
|
||||
|
||||
MotorSlopeTable sanei_genesys_slope_table(AsicType asic_type, int dpi, int exposure, int base_dpi,
|
||||
unsigned step_multiplier,
|
||||
const Motor_Profile& motor_profile)
|
||||
const MotorProfile& motor_profile)
|
||||
{
|
||||
unsigned target_speed_w = ((exposure * dpi) / base_dpi);
|
||||
|
||||
|
@ -1773,7 +1718,7 @@ MotorSlopeTable sanei_genesys_slope_table(AsicType asic_type, int dpi, int expos
|
|||
}
|
||||
|
||||
MotorSlopeTable create_slope_table_fastest(AsicType asic_type, unsigned step_multiplier,
|
||||
const Motor_Profile& motor_profile)
|
||||
const MotorProfile& motor_profile)
|
||||
{
|
||||
return create_slope_table(motor_profile.slope, motor_profile.slope.max_speed_w,
|
||||
motor_profile.step_type,
|
||||
|
|
|
@ -108,39 +108,6 @@
|
|||
#define GENESYS_GREEN 1
|
||||
#define GENESYS_BLUE 2
|
||||
|
||||
/* Flags */
|
||||
#define GENESYS_FLAG_UNTESTED (1 << 0) /**< Print a warning for these scanners */
|
||||
#define GENESYS_FLAG_14BIT_GAMMA (1 << 1) /**< use 14bit Gamma table instead of 12 */
|
||||
#define GENESYS_FLAG_XPA (1 << 3)
|
||||
#define GENESYS_FLAG_SKIP_WARMUP (1 << 4) /**< skip genesys_warmup() */
|
||||
/** @brief offset calibration flag
|
||||
* signals that the scanner does offset calibration. In this case off_calibration() and
|
||||
* coarse_gain_calibration() functions must be implemented
|
||||
*/
|
||||
#define GENESYS_FLAG_OFFSET_CALIBRATION (1 << 5)
|
||||
#define GENESYS_FLAG_SEARCH_START (1 << 6) /**< do start search before scanning */
|
||||
#define GENESYS_FLAG_REPARK (1 << 7) /**< repark head (and check for lock) by
|
||||
moving without scanning */
|
||||
#define GENESYS_FLAG_DARK_CALIBRATION (1 << 8) /**< do dark calibration */
|
||||
|
||||
#define GENESYS_FLAG_MUST_WAIT (1 << 10) /**< tells wether the scanner must wait for the head when parking */
|
||||
|
||||
|
||||
#define GENESYS_FLAG_HAS_UTA (1 << 11) /**< scanner has a transparency adapter */
|
||||
|
||||
#define GENESYS_FLAG_DARK_WHITE_CALIBRATION (1 << 12) /**< yet another calibration method. does white and dark shading in one run, depending on a black and a white strip*/
|
||||
#define GENESYS_FLAG_CUSTOM_GAMMA (1 << 13) /**< allow custom gamma tables */
|
||||
#define GENESYS_FLAG_NO_CALIBRATION (1 << 14) /**< allow scanners to use skip the calibration, needed for sheetfed scanners */
|
||||
#define GENESYS_FLAG_SIS_SENSOR (1 << 16) /**< handling of multi-segments sensors in software */
|
||||
#define GENESYS_FLAG_SHADING_NO_MOVE (1 << 17) /**< scanner doesn't move sensor during shading calibration */
|
||||
#define GENESYS_FLAG_SHADING_REPARK (1 << 18) /**< repark head between shading scans */
|
||||
#define GENESYS_FLAG_FULL_HWDPI_MODE (1 << 19) /**< scanner always use maximum hw dpi to setup the sensor */
|
||||
// scanner has infrared transparency scanning capability
|
||||
#define GENESYS_FLAG_HAS_UTA_INFRARED (1 << 20)
|
||||
// scanner calibration is handled on the host side
|
||||
#define GENESYS_FLAG_CALIBRATION_HOST_SIDE (1 << 21)
|
||||
#define GENESYS_FLAG_16BIT_DATA_INVERTED (1 << 22)
|
||||
|
||||
#define GENESYS_HAS_NO_BUTTONS 0 /**< scanner has no supported button */
|
||||
#define GENESYS_HAS_SCAN_SW (1 << 0) /**< scanner has SCAN button */
|
||||
#define GENESYS_HAS_FILE_SW (1 << 1) /**< scanner has FILE button */
|
||||
|
@ -215,22 +182,6 @@ struct Genesys_USB_Device_Entry {
|
|||
Genesys_Model model;
|
||||
};
|
||||
|
||||
/**
|
||||
* structure for motor database
|
||||
*/
|
||||
struct Motor_Profile
|
||||
{
|
||||
MotorId motor_id;
|
||||
int exposure; // used only to select the wanted motor
|
||||
StepType step_type; // default step type for given exposure
|
||||
MotorSlope slope;
|
||||
};
|
||||
|
||||
extern StaticInit<std::vector<Motor_Profile>> gl843_motor_profiles;
|
||||
extern StaticInit<std::vector<Motor_Profile>> gl846_motor_profiles;
|
||||
extern StaticInit<std::vector<Motor_Profile>> gl847_motor_profiles;
|
||||
extern StaticInit<std::vector<Motor_Profile>> gl124_motor_profiles;
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* common functions needed by low level specific functions */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
@ -335,16 +286,23 @@ void sanei_genesys_send_gamma_table(Genesys_Device* dev, const Genesys_Sensor& s
|
|||
|
||||
extern void sanei_genesys_stop_motor(Genesys_Device* dev);
|
||||
|
||||
extern void sanei_genesys_search_reference_point(Genesys_Device* dev, Genesys_Sensor& sensor,
|
||||
const uint8_t* src_data, int start_pixel, int dpi,
|
||||
int width, int height);
|
||||
|
||||
// moves the scan head by the specified steps at the motor base dpi
|
||||
void scanner_move(Genesys_Device& dev, ScanMethod scan_method, unsigned steps, Direction direction);
|
||||
|
||||
void scanner_move_back_home(Genesys_Device& dev, bool wait_until_home);
|
||||
void scanner_move_back_home_ta(Genesys_Device& dev);
|
||||
|
||||
/** Search for a full width black or white strip.
|
||||
This function searches for a black or white stripe across the scanning area.
|
||||
When searching backward, the searched area must completely be of the desired
|
||||
color since this area will be used for calibration which scans forward.
|
||||
|
||||
@param dev scanner device
|
||||
@param forward true if searching forward, false if searching backward
|
||||
@param black true if searching for a black strip, false for a white strip
|
||||
*/
|
||||
void scanner_search_strip(Genesys_Device& dev, bool forward, bool black);
|
||||
|
||||
void scanner_clear_scan_and_feed_counts(Genesys_Device& dev);
|
||||
|
||||
extern void sanei_genesys_write_file(const char* filename, const std::uint8_t* data,
|
||||
|
@ -373,22 +331,11 @@ void regs_set_optical_off(AsicType asic_type, Genesys_Register_Set& regs);
|
|||
void sanei_genesys_set_dpihw(Genesys_Register_Set& regs, const Genesys_Sensor& sensor,
|
||||
unsigned dpihw);
|
||||
|
||||
inline uint16_t sanei_genesys_fixup_exposure_value(uint16_t value)
|
||||
{
|
||||
if ((value & 0xff00) == 0) {
|
||||
value |= 0x100;
|
||||
}
|
||||
if ((value & 0x00ff) == 0) {
|
||||
value |= 0x1;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
inline SensorExposure sanei_genesys_fixup_exposure(SensorExposure exposure)
|
||||
{
|
||||
exposure.red = sanei_genesys_fixup_exposure_value(exposure.red);
|
||||
exposure.green = sanei_genesys_fixup_exposure_value(exposure.green);
|
||||
exposure.blue = sanei_genesys_fixup_exposure_value(exposure.blue);
|
||||
exposure.red = std::max<std::uint16_t>(1, exposure.red);
|
||||
exposure.green = std::max<std::uint16_t>(1, exposure.green);
|
||||
exposure.blue = std::max<std::uint16_t>(1, exposure.blue);
|
||||
return exposure;
|
||||
}
|
||||
|
||||
|
@ -404,15 +351,20 @@ void scanner_stop_action_no_move(Genesys_Device& dev, Genesys_Register_Set& regs
|
|||
|
||||
bool scanner_is_motor_stopped(Genesys_Device& dev);
|
||||
|
||||
const Motor_Profile& sanei_genesys_get_motor_profile(const std::vector<Motor_Profile>& motors,
|
||||
MotorId motor_id, int exposure);
|
||||
const MotorProfile* get_motor_profile_ptr(const std::vector<MotorProfile>& profiles,
|
||||
unsigned exposure,
|
||||
const ScanSession& session);
|
||||
|
||||
const MotorProfile& get_motor_profile(const std::vector<MotorProfile>& profiles,
|
||||
unsigned exposure,
|
||||
const ScanSession& session);
|
||||
|
||||
MotorSlopeTable sanei_genesys_slope_table(AsicType asic_type, int dpi, int exposure, int base_dpi,
|
||||
unsigned step_multiplier,
|
||||
const Motor_Profile& motor_profile);
|
||||
const MotorProfile& motor_profile);
|
||||
|
||||
MotorSlopeTable create_slope_table_fastest(AsicType asic_type, unsigned step_multiplier,
|
||||
const Motor_Profile& motor_profile);
|
||||
const MotorProfile& motor_profile);
|
||||
|
||||
/** @brief find lowest motor resolution for the device.
|
||||
* Parses the resolution list for motor and
|
||||
|
@ -451,7 +403,8 @@ extern void sanei_genesys_generate_gamma_buffer(Genesys_Device* dev,
|
|||
|
||||
void compute_session(const Genesys_Device* dev, ScanSession& s, const Genesys_Sensor& sensor);
|
||||
|
||||
void build_image_pipeline(Genesys_Device* dev, const ScanSession& session);
|
||||
void build_image_pipeline(Genesys_Device* dev, const Genesys_Sensor& sensor,
|
||||
const ScanSession& session);
|
||||
|
||||
std::uint8_t compute_frontend_gain(float value, float target_value,
|
||||
FrontendType frontend_type);
|
||||
|
@ -509,8 +462,8 @@ void genesys_init_sensor_tables();
|
|||
void genesys_init_frontend_tables();
|
||||
void genesys_init_gpo_tables();
|
||||
void genesys_init_motor_tables();
|
||||
void genesys_init_motor_profile_tables();
|
||||
void genesys_init_usb_device_tables();
|
||||
void verify_usb_device_tables();
|
||||
|
||||
template<class T>
|
||||
void debug_dump(unsigned level, const T& value)
|
||||
|
|
|
@ -164,15 +164,31 @@ std::ostream& operator<<(std::ostream& out, const MotorSlope& slope)
|
|||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const MotorProfile& profile)
|
||||
{
|
||||
out << "MotorProfile{\n"
|
||||
<< " max_exposure: " << profile.max_exposure << '\n'
|
||||
<< " step_type: " << profile.step_type << '\n'
|
||||
<< " motor_vref: " << profile.motor_vref << '\n'
|
||||
<< " resolutions: " << format_indent_braced_list(4, profile.resolutions) << '\n'
|
||||
<< " scan_methods: " << format_indent_braced_list(4, profile.scan_methods) << '\n'
|
||||
<< " slope: " << format_indent_braced_list(4, profile.slope) << '\n'
|
||||
<< '}';
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const Genesys_Motor& motor)
|
||||
{
|
||||
out << "Genesys_Motor{\n"
|
||||
<< " id: " << static_cast<unsigned>(motor.id) << '\n'
|
||||
<< " base_ydpi: " << motor.base_ydpi << '\n'
|
||||
<< " optical_ydpi: " << motor.optical_ydpi << '\n'
|
||||
<< " slopes: "
|
||||
<< format_indent_braced_list(4, format_vector_indent_braced(4, "MotorSlope",
|
||||
motor.slopes))
|
||||
<< " profiles: "
|
||||
<< format_indent_braced_list(4, format_vector_indent_braced(4, "MotorProfile",
|
||||
motor.profiles)) << '\n'
|
||||
<< " fast_profiles: "
|
||||
<< format_indent_braced_list(4, format_vector_indent_braced(4, "MotorProfile",
|
||||
motor.fast_profiles)) << '\n'
|
||||
<< '}';
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -44,9 +44,11 @@
|
|||
#ifndef BACKEND_GENESYS_MOTOR_H
|
||||
#define BACKEND_GENESYS_MOTOR_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include "enums.h"
|
||||
#include "sensor.h"
|
||||
|
||||
namespace genesys {
|
||||
|
||||
|
@ -137,6 +139,26 @@ MotorSlopeTable create_slope_table(const MotorSlope& slope, unsigned target_spee
|
|||
|
||||
std::ostream& operator<<(std::ostream& out, const MotorSlope& slope);
|
||||
|
||||
struct MotorProfile
|
||||
{
|
||||
MotorProfile() = default;
|
||||
MotorProfile(const MotorSlope& a_slope, StepType a_step_type, unsigned a_max_exposure) :
|
||||
slope{a_slope}, step_type{a_step_type}, max_exposure{a_max_exposure}
|
||||
{}
|
||||
|
||||
MotorSlope slope;
|
||||
StepType step_type = StepType::FULL;
|
||||
int motor_vref = -1;
|
||||
|
||||
// the resolutions this profile is good for
|
||||
ResolutionFilter resolutions = ResolutionFilter::ANY;
|
||||
// the scan method this profile is good for. If the list is empty, good for any method.
|
||||
ScanMethodFilter scan_methods = ScanMethodFilter::ANY;
|
||||
|
||||
unsigned max_exposure = 0; // 0 - any exposure
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const MotorProfile& profile);
|
||||
|
||||
struct Genesys_Motor
|
||||
{
|
||||
|
@ -149,24 +171,40 @@ struct Genesys_Motor
|
|||
// maximum resolution in y-direction. Unit: 1/inch
|
||||
int optical_ydpi = 0;
|
||||
// slopes to derive individual slopes from
|
||||
std::vector<MotorSlope> slopes;
|
||||
std::vector<MotorProfile> profiles;
|
||||
// slopes to derive individual slopes from for fast moving
|
||||
std::vector<MotorProfile> fast_profiles;
|
||||
|
||||
MotorSlope& get_slope(StepType step_type)
|
||||
MotorSlope& get_slope_with_step_type(StepType step_type)
|
||||
{
|
||||
return slopes[static_cast<unsigned>(step_type)];
|
||||
for (auto& p : profiles) {
|
||||
if (p.step_type == step_type)
|
||||
return p.slope;
|
||||
}
|
||||
throw SaneException("No motor profile with step type");
|
||||
}
|
||||
|
||||
const MotorSlope& get_slope(StepType step_type) const
|
||||
const MotorSlope& get_slope_with_step_type(StepType step_type) const
|
||||
{
|
||||
return slopes[static_cast<unsigned>(step_type)];
|
||||
for (const auto& p : profiles) {
|
||||
if (p.step_type == step_type)
|
||||
return p.slope;
|
||||
}
|
||||
throw SaneException("No motor profile with step type");
|
||||
}
|
||||
|
||||
StepType max_step_type() const
|
||||
{
|
||||
if (slopes.empty()) {
|
||||
throw std::runtime_error("Slopes table is empty");
|
||||
if (profiles.empty()) {
|
||||
throw std::runtime_error("Profiles table is empty");
|
||||
}
|
||||
return static_cast<StepType>(slopes.size() - 1);
|
||||
StepType step_type = StepType::FULL;
|
||||
for (const auto& p : profiles) {
|
||||
step_type = static_cast<StepType>(
|
||||
std::max(static_cast<unsigned>(step_type),
|
||||
static_cast<unsigned>(p.step_type)));
|
||||
}
|
||||
return step_type;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#ifndef BACKEND_GENESYS_REGISTER_H
|
||||
#define BACKEND_GENESYS_REGISTER_H
|
||||
|
||||
#include "enums.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -76,7 +77,7 @@ struct GenesysRegisterSetState
|
|||
bool is_lamp_on = false;
|
||||
bool is_xpa_on = false;
|
||||
bool is_motor_on = false;
|
||||
bool is_xpa_motor_on = false;
|
||||
MotorMode motor_mode = MotorMode::PRIMARY;
|
||||
};
|
||||
|
||||
template<class Value>
|
||||
|
|
|
@ -56,11 +56,6 @@ namespace genesys {
|
|||
class ScannerInterface
|
||||
{
|
||||
public:
|
||||
enum Flags {
|
||||
FLAG_NONE = 0,
|
||||
FLAG_SWAP_REGISTERS = 1 << 0,
|
||||
FLAG_SMALL_ADDRESS = 1 << 1
|
||||
};
|
||||
|
||||
virtual ~ScannerInterface();
|
||||
|
||||
|
@ -77,10 +72,10 @@ public:
|
|||
// GL646, GL841, GL843 have different ways to write to RAM and to gamma tables
|
||||
// FIXME: remove flags when updating tests
|
||||
virtual void write_buffer(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags = FLAG_NONE) = 0;
|
||||
std::size_t size) = 0;
|
||||
|
||||
virtual void write_gamma(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags = FLAG_NONE) = 0;
|
||||
std::size_t size) = 0;
|
||||
|
||||
// GL845, GL846, GL847 and GL124 have a uniform way to write to RAM tables
|
||||
virtual void write_ahb(std::uint32_t addr, std::uint32_t size, std::uint8_t* data) = 0;
|
||||
|
|
|
@ -351,7 +351,7 @@ void ScannerInterfaceUsb::bulk_write_data(std::uint8_t addr, std::uint8_t* data,
|
|||
}
|
||||
|
||||
void ScannerInterfaceUsb::write_buffer(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags)
|
||||
std::size_t size)
|
||||
{
|
||||
DBG_HELPER_ARGS(dbg, "type: 0x%02x, addr: 0x%08x, size: 0x%08zx", type, addr, size);
|
||||
if (dev_->model->asic_type != AsicType::GL646 &&
|
||||
|
@ -362,19 +362,9 @@ void ScannerInterfaceUsb::write_buffer(std::uint8_t type, std::uint32_t addr, st
|
|||
}
|
||||
|
||||
if (dev_->model->asic_type == AsicType::GL843) {
|
||||
if (flags & FLAG_SWAP_REGISTERS) {
|
||||
if (!(flags & FLAG_SMALL_ADDRESS)) {
|
||||
write_register(0x29, ((addr >> 20) & 0xff));
|
||||
}
|
||||
write_register(0x2a, ((addr >> 12) & 0xff));
|
||||
write_register(0x2b, ((addr >> 4) & 0xff));
|
||||
} else {
|
||||
write_register(0x2b, ((addr >> 4) & 0xff));
|
||||
write_register(0x2a, ((addr >> 12) & 0xff));
|
||||
if (!(flags & FLAG_SMALL_ADDRESS)) {
|
||||
write_register(0x29, ((addr >> 20) & 0xff));
|
||||
}
|
||||
}
|
||||
write_register(0x2b, ((addr >> 4) & 0xff));
|
||||
write_register(0x2a, ((addr >> 12) & 0xff));
|
||||
write_register(0x29, ((addr >> 20) & 0xff));
|
||||
} else {
|
||||
write_register(0x2b, ((addr >> 4) & 0xff));
|
||||
write_register(0x2a, ((addr >> 12) & 0xff));
|
||||
|
@ -383,24 +373,25 @@ void ScannerInterfaceUsb::write_buffer(std::uint8_t type, std::uint32_t addr, st
|
|||
}
|
||||
|
||||
void ScannerInterfaceUsb::write_gamma(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags)
|
||||
std::size_t size)
|
||||
{
|
||||
DBG_HELPER_ARGS(dbg, "type: 0x%02x, addr: 0x%08x, size: 0x%08zx", type, addr, size);
|
||||
if (dev_->model->asic_type != AsicType::GL646 &&
|
||||
dev_->model->asic_type != AsicType::GL841 &&
|
||||
if (dev_->model->asic_type != AsicType::GL841 &&
|
||||
dev_->model->asic_type != AsicType::GL843)
|
||||
{
|
||||
throw SaneException("Unsupported transfer mode");
|
||||
}
|
||||
|
||||
if (flags & FLAG_SWAP_REGISTERS) {
|
||||
write_register(0x5b, ((addr >> 12) & 0xff));
|
||||
write_register(0x5c, ((addr >> 4) & 0xff));
|
||||
} else {
|
||||
write_register(0x5c, ((addr >> 4) & 0xff));
|
||||
write_register(0x5b, ((addr >> 12) & 0xff));
|
||||
}
|
||||
write_register(0x5b, ((addr >> 12) & 0xff));
|
||||
write_register(0x5c, ((addr >> 4) & 0xff));
|
||||
bulk_write_data(type, data, size);
|
||||
|
||||
if (dev_->model->asic_type == AsicType::GL843) {
|
||||
// it looks like we need to reset the address so that subsequent buffer operations work.
|
||||
// Most likely the MTRTBL register is to blame.
|
||||
write_register(0x5b, 0);
|
||||
write_register(0x5c, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ScannerInterfaceUsb::write_ahb(std::uint32_t addr, std::uint32_t size, std::uint8_t* data)
|
||||
|
|
|
@ -67,9 +67,9 @@ public:
|
|||
void bulk_write_data(std::uint8_t addr, std::uint8_t* data, std::size_t size) override;
|
||||
|
||||
void write_buffer(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags) override;
|
||||
std::size_t size) override;
|
||||
void write_gamma(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags) override;
|
||||
std::size_t size) override;
|
||||
|
||||
void write_ahb(std::uint32_t addr, std::uint32_t size, std::uint8_t* data) override;
|
||||
|
||||
|
|
|
@ -122,6 +122,16 @@ std::ostream& operator<<(std::ostream& out, const ResolutionFilter& 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"
|
||||
|
@ -138,7 +148,6 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Sensor& sensor)
|
|||
<< " black_pixels: " << sensor.black_pixels << '\n'
|
||||
<< " dummy_pixel: " << sensor.dummy_pixel << '\n'
|
||||
<< " ccd_start_xoffset: " << sensor.ccd_start_xoffset << '\n'
|
||||
<< " sensor_pixels: " << sensor.sensor_pixels << '\n'
|
||||
<< " fau_gain_white_ref: " << sensor.fau_gain_white_ref << '\n'
|
||||
<< " gain_white_ref: " << sensor.gain_white_ref << '\n'
|
||||
<< " exposure: " << format_indent_braced_list(4, sensor.exposure) << '\n'
|
||||
|
@ -147,6 +156,7 @@ std::ostream& operator<<(std::ostream& out, const Genesys_Sensor& sensor)
|
|||
<< " segment_order: "
|
||||
<< format_indent_braced_list(4, format_vector_unsigned(4, sensor.segment_order)) << '\n'
|
||||
<< " stagger_config: " << format_indent_braced_list(4, sensor.stagger_config) << '\n'
|
||||
<< " 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'
|
||||
|
|
|
@ -290,6 +290,46 @@ void serialize(Stream& str, ResolutionFilter& x)
|
|||
}
|
||||
|
||||
|
||||
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;
|
||||
|
@ -334,8 +374,6 @@ struct Genesys_Sensor {
|
|||
int dummy_pixel = 0;
|
||||
// last pixel of CCD margin at optical resolution
|
||||
int ccd_start_xoffset = 0;
|
||||
// total pixels used by the sensor
|
||||
int sensor_pixels = 0;
|
||||
// TA CCD target code (reference gain)
|
||||
int fau_gain_white_ref = 0;
|
||||
// CCD target code (reference gain)
|
||||
|
@ -359,6 +397,9 @@ struct Genesys_Sensor {
|
|||
// high-enough resolution, every other pixel column is shifted
|
||||
StaggerConfig stagger_config;
|
||||
|
||||
// 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;
|
||||
|
@ -366,12 +407,10 @@ struct Genesys_Sensor {
|
|||
// red, green and blue gamma coefficient for default gamma tables
|
||||
AssignableArray<float, 3> gamma;
|
||||
|
||||
std::function<unsigned(const Genesys_Sensor&, unsigned)> get_logical_hwdpi_fun;
|
||||
std::function<unsigned(const Genesys_Sensor&, unsigned)> get_register_hwdpi_fun;
|
||||
std::function<unsigned(const Genesys_Sensor&, unsigned)> get_ccd_size_divisor_fun;
|
||||
std::function<unsigned(const Genesys_Sensor&, unsigned)> get_hwdpi_divisor_fun;
|
||||
|
||||
unsigned get_logical_hwdpi(unsigned xres) const { return get_logical_hwdpi_fun(*this, xres); }
|
||||
unsigned get_register_hwdpi(unsigned xres) const { return get_register_hwdpi_fun(*this, xres); }
|
||||
unsigned get_ccd_size_divisor_for_dpi(unsigned xres) const
|
||||
{
|
||||
|
@ -412,7 +451,6 @@ struct Genesys_Sensor {
|
|||
black_pixels == other.black_pixels &&
|
||||
dummy_pixel == other.dummy_pixel &&
|
||||
ccd_start_xoffset == other.ccd_start_xoffset &&
|
||||
sensor_pixels == other.sensor_pixels &&
|
||||
fau_gain_white_ref == other.fau_gain_white_ref &&
|
||||
gain_white_ref == other.gain_white_ref &&
|
||||
exposure == other.exposure &&
|
||||
|
@ -420,6 +458,7 @@ struct Genesys_Sensor {
|
|||
segment_size == other.segment_size &&
|
||||
segment_order == other.segment_order &&
|
||||
stagger_config == other.stagger_config &&
|
||||
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 &&
|
||||
|
@ -438,7 +477,6 @@ void serialize(Stream& str, Genesys_Sensor& x)
|
|||
serialize(str, x.black_pixels);
|
||||
serialize(str, x.dummy_pixel);
|
||||
serialize(str, x.ccd_start_xoffset);
|
||||
serialize(str, x.sensor_pixels);
|
||||
serialize(str, x.fau_gain_white_ref);
|
||||
serialize(str, x.gain_white_ref);
|
||||
serialize_newline(str);
|
||||
|
@ -453,6 +491,8 @@ void serialize(Stream& str, Genesys_Sensor& x)
|
|||
serialize_newline(str);
|
||||
serialize(str, x.stagger_config);
|
||||
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);
|
||||
|
|
|
@ -72,14 +72,20 @@ std::ostream& operator<<(std::ostream& out, const SetupParams& params)
|
|||
{
|
||||
StreamStateSaver state_saver{out};
|
||||
|
||||
bool reverse = has_flag(params.flags, ScanFlag::REVERSE);
|
||||
|
||||
out << "SetupParams{\n"
|
||||
<< " xres: " << params.xres << " yres: " << params.yres << '\n'
|
||||
<< " lines: " << params.lines << '\n'
|
||||
<< " pixels per line (actual): " << params.pixels << '\n'
|
||||
<< " pixels per line (requested): " << params.requested_pixels << '\n'
|
||||
<< " xres: " << params.xres
|
||||
<< " startx: " << params.startx
|
||||
<< " pixels per line (actual): " << params.pixels
|
||||
<< " pixels per line (requested): " << params.requested_pixels << '\n'
|
||||
|
||||
<< " yres: " << params.yres
|
||||
<< " lines: " << params.lines
|
||||
<< " starty: " << params.starty << (reverse ? " (reverse)" : "") << '\n'
|
||||
|
||||
<< " depth: " << params.depth << '\n'
|
||||
<< " channels: " << params.channels << '\n'
|
||||
<< " startx: " << params.startx << " starty: " << params.starty << '\n'
|
||||
<< " scan_mode: " << params.scan_mode << '\n'
|
||||
<< " color_filter: " << params.color_filter << '\n'
|
||||
<< " flags: " << params.flags << '\n'
|
||||
|
@ -87,6 +93,45 @@ std::ostream& operator<<(std::ostream& out, const SetupParams& params)
|
|||
return out;
|
||||
}
|
||||
|
||||
bool ScanSession::operator==(const ScanSession& other) const
|
||||
{
|
||||
return params == other.params &&
|
||||
computed == other.computed &&
|
||||
hwdpi_divisor == other.hwdpi_divisor &&
|
||||
ccd_size_divisor == other.ccd_size_divisor &&
|
||||
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_pixels == other.output_pixels &&
|
||||
output_channel_bytes == other.output_channel_bytes &&
|
||||
output_line_bytes == other.output_line_bytes &&
|
||||
output_line_bytes_raw == other.output_line_bytes_raw &&
|
||||
output_line_bytes_requested == other.output_line_bytes_requested &&
|
||||
output_line_count == other.output_line_count &&
|
||||
output_total_bytes_raw == other.output_total_bytes_raw &&
|
||||
output_total_bytes == other.output_total_bytes &&
|
||||
num_staggered_lines == other.num_staggered_lines &&
|
||||
max_color_shift_lines == other.max_color_shift_lines &&
|
||||
color_shift_lines_r == other.color_shift_lines_r &&
|
||||
color_shift_lines_g == other.color_shift_lines_g &&
|
||||
color_shift_lines_b == other.color_shift_lines_b &&
|
||||
segment_count == other.segment_count &&
|
||||
pixel_startx == other.pixel_startx &&
|
||||
pixel_endx == other.pixel_endx &&
|
||||
pixel_count_multiplier == other.pixel_count_multiplier &&
|
||||
conseq_pixel_dist == other.conseq_pixel_dist &&
|
||||
output_segment_pixel_group_count == other.output_segment_pixel_group_count &&
|
||||
output_segment_start_offset == other.output_segment_start_offset &&
|
||||
buffer_size_read == other.buffer_size_read &&
|
||||
enable_ledadd == other.enable_ledadd &&
|
||||
use_host_side_calib == other.use_host_side_calib &&
|
||||
pipeline_needs_reorder == other.pipeline_needs_reorder &&
|
||||
pipeline_needs_ccd == other.pipeline_needs_ccd &&
|
||||
pipeline_needs_shrink == other.pipeline_needs_shrink;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const ScanSession& session)
|
||||
{
|
||||
out << "ScanSession{\n"
|
||||
|
@ -96,6 +141,7 @@ std::ostream& operator<<(std::ostream& out, const ScanSession& session)
|
|||
<< " 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_pixels: " << session.output_pixels << '\n'
|
||||
<< " output_line_bytes: " << session.output_line_bytes << '\n'
|
||||
|
@ -114,9 +160,8 @@ std::ostream& operator<<(std::ostream& out, const ScanSession& session)
|
|||
<< " output_segment_pixel_group_count: "
|
||||
<< session.output_segment_pixel_group_count << '\n'
|
||||
<< " buffer_size_read: " << session.buffer_size_read << '\n'
|
||||
<< " buffer_size_read: " << session.buffer_size_lines << '\n'
|
||||
<< " buffer_size_shrink: " << session.buffer_size_shrink << '\n'
|
||||
<< " buffer_size_out: " << session.buffer_size_out << '\n'
|
||||
<< " enable_ledadd: " << session.enable_ledadd << '\n'
|
||||
<< " use_host_side_calib: " << session.use_host_side_calib << '\n'
|
||||
<< " filters: "
|
||||
<< (session.pipeline_needs_reorder ? " reorder": "")
|
||||
<< (session.pipeline_needs_ccd ? " ccd": "")
|
||||
|
|
|
@ -60,9 +60,9 @@ struct Genesys_Settings
|
|||
unsigned yres = 0;
|
||||
|
||||
//x start on scan table in mm
|
||||
double tl_x = 0;
|
||||
float tl_x = 0;
|
||||
// y start on scan table in mm
|
||||
double tl_y = 0;
|
||||
float tl_y = 0;
|
||||
|
||||
// number of lines at scan resolution
|
||||
unsigned int lines = 0;
|
||||
|
@ -116,7 +116,7 @@ struct SetupParams {
|
|||
unsigned xres = NOT_SET;
|
||||
// resolution in y direction
|
||||
unsigned yres = NOT_SET;
|
||||
// start pixel in X direction, from dummy_pixel + 1
|
||||
// start pixel in X direction, from dummy_pixel + 1. Counted in terms of xres.
|
||||
unsigned startx = NOT_SET;
|
||||
// start pixel in Y direction, counted according to base_ydpi
|
||||
unsigned starty = NOT_SET;
|
||||
|
@ -228,6 +228,9 @@ struct ScanSession {
|
|||
// only on gl846, g847
|
||||
unsigned optical_pixels_raw = 0;
|
||||
|
||||
// the number of optical scan lines. Equal to output_line_count on CCD scanners.
|
||||
unsigned optical_line_count = 0;
|
||||
|
||||
// the resolution of the output data.
|
||||
// gl843-only
|
||||
unsigned output_resolution = 0;
|
||||
|
@ -297,15 +300,15 @@ struct ScanSession {
|
|||
// Currently it's always zero.
|
||||
unsigned output_segment_start_offset = 0;
|
||||
|
||||
// the sizes of the corresponding buffers
|
||||
// the size of the read buffer.
|
||||
size_t buffer_size_read = 0;
|
||||
size_t buffer_size_lines = 0;
|
||||
size_t buffer_size_shrink = 0;
|
||||
size_t buffer_size_out = 0;
|
||||
|
||||
// whether to enable ledadd functionality
|
||||
bool enable_ledadd = false;
|
||||
|
||||
// whether calibration should be performed host-side
|
||||
bool use_host_side_calib = false;
|
||||
|
||||
// what pipeline modifications are needed
|
||||
bool pipeline_needs_reorder = false;
|
||||
bool pipeline_needs_ccd = false;
|
||||
|
@ -317,10 +320,53 @@ struct ScanSession {
|
|||
throw std::runtime_error("ScanSession is not computed");
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const ScanSession& other) const;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const ScanSession& session);
|
||||
|
||||
template<class Stream>
|
||||
void serialize(Stream& str, ScanSession& x)
|
||||
{
|
||||
serialize(str, x.params);
|
||||
serialize_newline(str);
|
||||
serialize(str, x.computed);
|
||||
serialize(str, x.hwdpi_divisor);
|
||||
serialize(str, x.ccd_size_divisor);
|
||||
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_pixels);
|
||||
serialize(str, x.output_channel_bytes);
|
||||
serialize(str, x.output_line_bytes);
|
||||
serialize(str, x.output_line_bytes_raw);
|
||||
serialize(str, x.output_line_bytes_requested);
|
||||
serialize(str, x.output_line_count);
|
||||
serialize(str, x.output_total_bytes_raw);
|
||||
serialize(str, x.output_total_bytes);
|
||||
serialize(str, x.num_staggered_lines);
|
||||
serialize(str, x.max_color_shift_lines);
|
||||
serialize(str, x.color_shift_lines_r);
|
||||
serialize(str, x.color_shift_lines_g);
|
||||
serialize(str, x.color_shift_lines_b);
|
||||
serialize(str, x.segment_count);
|
||||
serialize(str, x.pixel_startx);
|
||||
serialize(str, x.pixel_endx);
|
||||
serialize(str, x.pixel_count_multiplier);
|
||||
serialize(str, x.conseq_pixel_dist);
|
||||
serialize(str, x.output_segment_pixel_group_count);
|
||||
serialize(str, x.output_segment_start_offset);
|
||||
serialize(str, x.buffer_size_read);
|
||||
serialize(str, x.enable_ledadd);
|
||||
serialize(str, x.use_host_side_calib);
|
||||
serialize(str, x.pipeline_needs_reorder);
|
||||
serialize(str, x.pipeline_needs_ccd);
|
||||
serialize(str, x.pipeline_needs_shrink);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const SANE_Parameters& params);
|
||||
|
||||
} // namespace genesys
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -53,12 +53,14 @@ void genesys_init_motor_tables()
|
|||
{
|
||||
s_motors.init();
|
||||
|
||||
MotorProfile profile;
|
||||
|
||||
Genesys_Motor motor;
|
||||
motor.id = MotorId::UMAX;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 2400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
|
||||
motor.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 +68,8 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::MD_5345; // MD5345/6228/6471
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 2400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(2000, 1375, 128));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(2000, 1375, 128));
|
||||
motor.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));
|
||||
|
||||
|
||||
|
@ -75,17 +77,17 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::ST24;
|
||||
motor.base_ydpi = 2400;
|
||||
motor.optical_ydpi = 2400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(2289, 2100, 128));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(2289, 2100, 128));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(2289, 2100, 128), StepType::FULL, 0});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(2289, 2100, 128), StepType::HALF, 0});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
motor = Genesys_Motor();
|
||||
motor.id = MotorId::HP3670;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 2400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
|
||||
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));
|
||||
|
||||
|
||||
|
@ -93,8 +95,8 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::HP2400;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 1200;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 3000, 128));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(11000, 3000, 128), StepType::FULL, 0});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(11000, 3000, 128), StepType::HALF, 0});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -102,8 +104,8 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::HP2300;
|
||||
motor.base_ydpi = 600;
|
||||
motor.optical_ydpi = 1200;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3200, 1200, 128));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3200, 1200, 128));
|
||||
motor.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));
|
||||
|
||||
|
||||
|
@ -111,8 +113,8 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::CANON_LIDE_35;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 2400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1400, 60));
|
||||
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});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -120,8 +122,8 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::XP200;
|
||||
motor.base_ydpi = 600;
|
||||
motor.optical_ydpi = 600;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(3500, 1300, 60), StepType::FULL, 0});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(3500, 1300, 60), StepType::HALF, 0});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -130,8 +132,8 @@ void genesys_init_motor_tables()
|
|||
motor.base_ydpi = 300;
|
||||
motor.optical_ydpi = 600;
|
||||
// works best with GPIO10, GPIO14 off
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3700, 3700, 2));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 11000, 2));
|
||||
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});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -139,8 +141,8 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::DP665;
|
||||
motor.base_ydpi = 750;
|
||||
motor.optical_ydpi = 1500;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 2500, 10));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 11000, 2));
|
||||
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});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -148,8 +150,8 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::ROADWARRIOR;
|
||||
motor.base_ydpi = 750;
|
||||
motor.optical_ydpi = 1500;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 2600, 10));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(11000, 11000, 2));
|
||||
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});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -157,8 +159,8 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::DSMOBILE_600;
|
||||
motor.base_ydpi = 750;
|
||||
motor.optical_ydpi = 1500;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(6666, 3700, 8));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(6666, 3700, 8));
|
||||
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});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -166,9 +168,12 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::CANON_LIDE_100;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 6400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 127));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1500, 127));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3 * 2712, 3 * 2712, 16));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 864, 255),
|
||||
StepType::HALF, 1432});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 864, 279),
|
||||
StepType::QUARTER, 2712});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(31680, 864, 247),
|
||||
StepType::EIGHTH, 5280});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -176,9 +181,14 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::CANON_LIDE_200;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 6400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 127));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1500, 127));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3 * 2712, 3 * 2712, 16));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 864, 255),
|
||||
StepType::HALF, 1432});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 864, 279),
|
||||
StepType::QUARTER, 2712});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(31680, 864, 247),
|
||||
StepType::EIGHTH, 5280});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(31680, 864, 247),
|
||||
StepType::EIGHTH, 10416});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -186,9 +196,16 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::CANON_LIDE_700;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 6400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 127));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1500, 127));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3 * 2712, 3 * 2712, 16));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 534, 255),
|
||||
StepType::HALF, 1424});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 534, 255),
|
||||
StepType::HALF, 1504});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 2022, 127),
|
||||
StepType::HALF, 2696});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 534, 255),
|
||||
StepType::HALF, 2848});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(46876, 15864, 2),
|
||||
StepType::EIGHTH, 10576});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -196,9 +213,8 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::KVSS080;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 1200;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(22222, 500, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(22222, 500, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(22222, 500, 246));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(44444, 500, 489),
|
||||
StepType::HALF, 8000});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -206,9 +222,14 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::G4050;
|
||||
motor.base_ydpi = 2400;
|
||||
motor.optical_ydpi = 9600;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(7842, 320, 602),
|
||||
StepType::HALF, 8016});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(9422, 254, 1004),
|
||||
StepType::HALF, 15624});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(28032, 2238, 604),
|
||||
StepType::HALF, 56064});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(42752, 1706, 610),
|
||||
StepType::QUARTER, 42752});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -216,9 +237,27 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::CANON_4400F;
|
||||
motor.base_ydpi = 2400;
|
||||
motor.optical_ydpi = 9600;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(28597 * 2, 727 * 2, 200);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 1;
|
||||
profile.resolutions = { 300, 600 };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(28597 * 2, 727 * 2, 200);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 0;
|
||||
profile.resolutions = { 1200, 2400, 4800, 9600 };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(28597 * 2, 279 * 2, 1000);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 0;
|
||||
motor.fast_profiles.push_back(std::move(profile));
|
||||
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -226,9 +265,31 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::CANON_8400F;
|
||||
motor.base_ydpi = 1600;
|
||||
motor.optical_ydpi = 6400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(20202 * 4, 333 * 4, 100);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 0;
|
||||
profile.resolutions = ResolutionFilter::ANY;
|
||||
profile.scan_methods = { ScanMethod::FLATBED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(65535 * 4, 333 * 4, 100);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 2;
|
||||
profile.resolutions = ResolutionFilter::ANY;
|
||||
profile.scan_methods = { ScanMethod::TRANSPARENCY, ScanMethod::TRANSPARENCY_INFRARED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(65535 * 4, 333 * 4, 200);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 2;
|
||||
profile.resolutions = ResolutionFilter::ANY;
|
||||
profile.scan_methods = ScanMethodFilter::ANY;
|
||||
motor.fast_profiles.push_back(std::move(profile));
|
||||
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -236,9 +297,64 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::CANON_8600F;
|
||||
motor.base_ydpi = 2400;
|
||||
motor.optical_ydpi = 9600;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3961, 240, 246));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 3;
|
||||
profile.resolutions = { 300, 600 };
|
||||
profile.scan_methods = { ScanMethod::FLATBED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 2;
|
||||
profile.resolutions = { 1200, 2400 };
|
||||
profile.scan_methods = { ScanMethod::FLATBED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 2;
|
||||
profile.resolutions = { 4800 };
|
||||
profile.scan_methods = { ScanMethod::FLATBED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 2;
|
||||
profile.resolutions = { 300, 600 };
|
||||
profile.scan_methods = { ScanMethod::TRANSPARENCY,
|
||||
ScanMethod::TRANSPARENCY_INFRARED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 1;
|
||||
profile.resolutions = { 1200, 2400 };
|
||||
profile.scan_methods = { ScanMethod::TRANSPARENCY,
|
||||
ScanMethod::TRANSPARENCY_INFRARED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 0;
|
||||
profile.resolutions = { 4800 };
|
||||
profile.scan_methods = { ScanMethod::TRANSPARENCY,
|
||||
ScanMethod::TRANSPARENCY_INFRARED };
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(59240, 582, 1020);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 2;
|
||||
motor.fast_profiles.push_back(std::move(profile));
|
||||
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -246,7 +362,14 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::CANON_LIDE_110;
|
||||
motor.base_ydpi = 4800;
|
||||
motor.optical_ydpi = 9600;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 256));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 335, 255),
|
||||
StepType::FULL, 2768});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 335, 469),
|
||||
StepType::HALF, 5360});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 2632, 3),
|
||||
StepType::HALF, 10528});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 10432, 3),
|
||||
StepType::QUARTER, 20864});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -254,7 +377,14 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::CANON_LIDE_120;
|
||||
motor.base_ydpi = 4800;
|
||||
motor.optical_ydpi = 9600;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 256));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 864, 127),
|
||||
StepType::FULL, 4608});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 2010, 63),
|
||||
StepType::HALF, 5360});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62464, 2632, 3),
|
||||
StepType::QUARTER, 10528});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62592, 10432, 5),
|
||||
StepType::QUARTER, 20864});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -262,7 +392,14 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::CANON_LIDE_210;
|
||||
motor.base_ydpi = 4800;
|
||||
motor.optical_ydpi = 9600;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3000, 1000, 256));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 335, 255),
|
||||
StepType::FULL, 2768});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 335, 469),
|
||||
StepType::HALF, 5360});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 2632, 3),
|
||||
StepType::HALF, 10528});
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(62496, 10432, 4),
|
||||
StepType::QUARTER, 20864});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -270,8 +407,8 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::PLUSTEK_OPTICPRO_3600;
|
||||
motor.base_ydpi = 1200;
|
||||
motor.optical_ydpi = 2400;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 3250, 60));
|
||||
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});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -279,6 +416,19 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::PLUSTEK_OPTICFILM_7200I;
|
||||
motor.base_ydpi = 3600;
|
||||
motor.optical_ydpi = 3600;
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(34722 * 2, 454 * 2, 40);
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.motor_vref = 3;
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(34722 * 2, 454 * 2, 40);
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.motor_vref = 0;
|
||||
motor.fast_profiles.push_back(std::move(profile));
|
||||
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -286,6 +436,19 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::PLUSTEK_OPTICFILM_7300;
|
||||
motor.base_ydpi = 3600;
|
||||
motor.optical_ydpi = 3600;
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(56818 * 4, 454 * 4, 30);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 3;
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(56818 * 4, 454 * 4, 30);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 0;
|
||||
motor.fast_profiles.push_back(std::move(profile));
|
||||
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -293,6 +456,19 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::PLUSTEK_OPTICFILM_7500I;
|
||||
motor.base_ydpi = 3600;
|
||||
motor.optical_ydpi = 3600;
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(56818 * 4, 454 * 4, 30);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 3;
|
||||
motor.profiles.push_back(std::move(profile));
|
||||
|
||||
profile = MotorProfile();
|
||||
profile.slope = MotorSlope::create_from_steps(56818 * 4, 454 * 4, 30);
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.motor_vref = 0;
|
||||
motor.fast_profiles.push_back(std::move(profile));
|
||||
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -300,8 +476,8 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::IMG101;
|
||||
motor.base_ydpi = 600;
|
||||
motor.optical_ydpi = 1200;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 3250, 60));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(22000, 1000, 1017),
|
||||
StepType::HALF, 11000});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -309,8 +485,8 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::PLUSTEK_OPTICBOOK_3800;
|
||||
motor.base_ydpi = 600;
|
||||
motor.optical_ydpi = 1200;
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 1300, 60));
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(3500, 3250, 60));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(22000, 1000, 1017),
|
||||
StepType::HALF, 11000});
|
||||
s_motors->push_back(std::move(motor));
|
||||
|
||||
|
||||
|
@ -318,7 +494,7 @@ void genesys_init_motor_tables()
|
|||
motor.id = MotorId::CANON_LIDE_80;
|
||||
motor.base_ydpi = 2400;
|
||||
motor.optical_ydpi = 4800; // 9600
|
||||
motor.slopes.push_back(MotorSlope::create_from_steps(9560, 1912, 31));
|
||||
motor.profiles.push_back({MotorSlope::create_from_steps(9560, 1912, 31), StepType::FULL, 0});
|
||||
s_motors->push_back(std::move(motor));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,380 +0,0 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
|
||||
Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
|
||||
|
||||
This file is part of the SANE package.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA.
|
||||
|
||||
As a special exception, the authors of SANE give permission for
|
||||
additional uses of the libraries contained in this release of SANE.
|
||||
|
||||
The exception is that, if you link a SANE library with other files
|
||||
to produce an executable, this does not by itself cause the
|
||||
resulting executable to be covered by the GNU General Public
|
||||
License. Your use of that executable is in no way restricted on
|
||||
account of linking the SANE library code into it.
|
||||
|
||||
This exception does not, however, invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public
|
||||
License.
|
||||
|
||||
If you submit changes to SANE to the maintainers to be included in
|
||||
a subsequent release, you agree by submitting the changes that
|
||||
those changes may be distributed with this exception intact.
|
||||
|
||||
If you write modifications of your own for SANE, it is your choice
|
||||
whether to permit this exception to apply to your modifications.
|
||||
If you do not wish that, delete this exception notice.
|
||||
*/
|
||||
|
||||
#define DEBUG_DECLARE_ONLY
|
||||
|
||||
#include "low.h"
|
||||
|
||||
namespace genesys {
|
||||
|
||||
StaticInit<std::vector<Motor_Profile>> gl843_motor_profiles;
|
||||
|
||||
void genesys_init_motor_profile_tables_gl843()
|
||||
{
|
||||
gl843_motor_profiles.init();
|
||||
|
||||
auto profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::KVSS080;
|
||||
profile.exposure = 8000;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(44444, 500, 489);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::G4050;
|
||||
profile.exposure = 8016;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(7842, 320, 602);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::G4050;
|
||||
profile.exposure = 15624;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(9422, 254, 1004);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::G4050;
|
||||
profile.exposure = 42752;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(42752, 1706, 610);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::G4050;
|
||||
profile.exposure = 56064;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(28032, 2238, 604);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_4400F;
|
||||
profile.exposure = 11640;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(49152, 484, 1014);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_8400F;
|
||||
profile.exposure = 50000;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(8743, 300, 794);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_8600F;
|
||||
profile.exposure = 0x59d8;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
// FIXME: if the exposure is lower then we'll select another motor
|
||||
profile.slope = MotorSlope::create_from_steps(54612, 1500, 219);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::PLUSTEK_OPTICFILM_7200I;
|
||||
profile.exposure = 0;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(39682, 1191, 15);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::PLUSTEK_OPTICFILM_7300;
|
||||
profile.exposure = 0x2f44;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(31250, 1512, 6);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::PLUSTEK_OPTICFILM_7500I;
|
||||
profile.exposure = 0;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(31250, 1375, 7);
|
||||
gl843_motor_profiles->push_back(profile);
|
||||
}
|
||||
|
||||
StaticInit<std::vector<Motor_Profile>> gl846_motor_profiles;
|
||||
|
||||
void genesys_init_motor_profile_tables_gl846()
|
||||
{
|
||||
gl846_motor_profiles.init();
|
||||
|
||||
auto profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::IMG101;
|
||||
profile.exposure = 11000;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(22000, 1000, 1017);
|
||||
|
||||
gl846_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::PLUSTEK_OPTICBOOK_3800;
|
||||
profile.exposure = 11000;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(22000, 1000, 1017);
|
||||
gl846_motor_profiles->push_back(profile);
|
||||
}
|
||||
|
||||
/**
|
||||
* database of motor profiles
|
||||
*/
|
||||
|
||||
StaticInit<std::vector<Motor_Profile>> gl847_motor_profiles;
|
||||
|
||||
void genesys_init_motor_profile_tables_gl847()
|
||||
{
|
||||
gl847_motor_profiles.init();
|
||||
|
||||
auto profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_100;
|
||||
profile.exposure = 2848;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_100;
|
||||
profile.exposure = 1424;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_100;
|
||||
profile.exposure = 1432;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_100;
|
||||
profile.exposure = 2712;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 279);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_100;
|
||||
profile.exposure = 5280;
|
||||
profile.step_type = StepType::EIGHTH;
|
||||
profile.slope = MotorSlope::create_from_steps(31680, 534, 247);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_200;
|
||||
profile.exposure = 2848;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_200;
|
||||
profile.exposure = 1424;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_200;
|
||||
profile.exposure = 1432;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_200;
|
||||
profile.exposure = 2712;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 279);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_200;
|
||||
profile.exposure = 5280;
|
||||
profile.step_type = StepType::EIGHTH;
|
||||
profile.slope = MotorSlope::create_from_steps(31680, 534, 247);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_200;
|
||||
profile.exposure = 10416;
|
||||
profile.step_type = StepType::EIGHTH;
|
||||
profile.slope = MotorSlope::create_from_steps(31680, 534, 247);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_700;
|
||||
profile.exposure = 2848;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_700;
|
||||
profile.exposure = 1424;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_700;
|
||||
profile.exposure = 1504;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 534, 255);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_700;
|
||||
profile.exposure = 2696;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 2022, 127);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_700;
|
||||
profile.exposure = 10576;
|
||||
profile.step_type = StepType::EIGHTH;
|
||||
profile.slope = MotorSlope::create_from_steps(46876, 15864, 2);
|
||||
gl847_motor_profiles->push_back(profile);
|
||||
}
|
||||
|
||||
StaticInit<std::vector<Motor_Profile>> gl124_motor_profiles;
|
||||
|
||||
void genesys_init_motor_profile_tables_gl124()
|
||||
{
|
||||
gl124_motor_profiles.init();
|
||||
|
||||
// NEXT LPERIOD=PREVIOUS*2-192
|
||||
Motor_Profile profile;
|
||||
profile.motor_id = MotorId::CANON_LIDE_110;
|
||||
profile.exposure = 2768;
|
||||
profile.step_type = StepType::FULL;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 335, 255);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_110;
|
||||
profile.exposure = 5360;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 335, 469);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_110;
|
||||
profile.exposure = 10528;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 2632, 3);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_110;
|
||||
profile.exposure = 20864;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 10432, 3);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_120;
|
||||
profile.exposure = 4608;
|
||||
profile.step_type = StepType::FULL;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 864, 127);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_120;
|
||||
profile.exposure = 5360;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 2010, 63);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_120;
|
||||
profile.exposure = 10528;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(62464, 2632, 3);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_120;
|
||||
profile.exposure = 20864;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(62592, 10432, 5);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_210;
|
||||
profile.exposure = 2768;
|
||||
profile.step_type = StepType::FULL;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 335, 255);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_210;
|
||||
profile.exposure = 5360;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 335, 469);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_210;
|
||||
profile.exposure = 10528;
|
||||
profile.step_type = StepType::HALF;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 2632, 3);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
|
||||
profile = Motor_Profile();
|
||||
profile.motor_id = MotorId::CANON_LIDE_210;
|
||||
profile.exposure = 20864;
|
||||
profile.step_type = StepType::QUARTER;
|
||||
profile.slope = MotorSlope::create_from_steps(62496, 10432, 4);
|
||||
gl124_motor_profiles->push_back(profile);
|
||||
}
|
||||
|
||||
void genesys_init_motor_profile_tables()
|
||||
{
|
||||
genesys_init_motor_profile_tables_gl843();
|
||||
genesys_init_motor_profile_tables_gl846();
|
||||
genesys_init_motor_profile_tables_gl847();
|
||||
genesys_init_motor_profile_tables_gl124();
|
||||
}
|
||||
|
||||
} // namespace genesys
|
Plik diff jest za duży
Load Diff
|
@ -137,23 +137,21 @@ void TestScannerInterface::bulk_write_data(std::uint8_t addr, std::uint8_t* data
|
|||
}
|
||||
|
||||
void TestScannerInterface::write_buffer(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags)
|
||||
std::size_t size)
|
||||
{
|
||||
(void) type;
|
||||
(void) addr;
|
||||
(void) data;
|
||||
(void) size;
|
||||
(void) flags;
|
||||
}
|
||||
|
||||
void TestScannerInterface::write_gamma(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags)
|
||||
std::size_t size)
|
||||
{
|
||||
(void) type;
|
||||
(void) addr;
|
||||
(void) data;
|
||||
(void) size;
|
||||
(void) flags;
|
||||
}
|
||||
|
||||
void TestScannerInterface::write_ahb(std::uint32_t addr, std::uint32_t size, std::uint8_t* data)
|
||||
|
|
|
@ -74,9 +74,9 @@ public:
|
|||
void bulk_write_data(std::uint8_t addr, std::uint8_t* data, std::size_t size) override;
|
||||
|
||||
void write_buffer(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags) override;
|
||||
std::size_t size) override;
|
||||
void write_gamma(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
|
||||
std::size_t size, Flags flags) override;
|
||||
std::size_t size) override;
|
||||
void write_ahb(std::uint32_t addr, std::uint32_t size, std::uint8_t* data) override;
|
||||
|
||||
std::uint16_t read_fe_register(std::uint8_t address) override;
|
||||
|
|
|
@ -50,8 +50,31 @@
|
|||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace genesys {
|
||||
|
||||
// just like SANE_FIX and SANE_UNFIX except that the conversion is done by a function and argument
|
||||
// precision is handled correctly
|
||||
inline SANE_Word double_to_fixed(double v)
|
||||
{
|
||||
return static_cast<SANE_Word>(v * (1 << SANE_FIXED_SCALE_SHIFT));
|
||||
}
|
||||
|
||||
inline SANE_Word float_to_fixed(float v)
|
||||
{
|
||||
return static_cast<SANE_Word>(v * (1 << SANE_FIXED_SCALE_SHIFT));
|
||||
}
|
||||
|
||||
inline float fixed_to_float(SANE_Word v)
|
||||
{
|
||||
return static_cast<float>(v) / (1 << SANE_FIXED_SCALE_SHIFT);
|
||||
}
|
||||
|
||||
inline double fixed_to_double(SANE_Word v)
|
||||
{
|
||||
return static_cast<double>(v) / (1 << SANE_FIXED_SCALE_SHIFT);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void compute_array_percentile_approx(T* result, const T* data,
|
||||
std::size_t line_count, std::size_t elements_per_line,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
Copyright (C) 20020 Ralph Little <skelband@gmail.com>
|
||||
Copyright (C) 2003 Martijn van Oosterhout <kleptog@svana.org>
|
||||
Copyright (C) 2003 Thomas Soumarmon <thomas.soumarmon@cogitae.net>
|
||||
|
||||
|
@ -138,6 +139,16 @@ typedef struct
|
|||
}
|
||||
TScanParams;
|
||||
|
||||
/*
|
||||
* Panel settings. We can read and set these.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
SANE_Word copycount; // 0..99 LCD display value
|
||||
SANE_Word bwcolour; // 1=Colour or 2=Black/White from scan type LEDs
|
||||
}
|
||||
TPanelInfo;
|
||||
|
||||
|
||||
#endif /* NO _HP5400_H_ */
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
Copyright (C) 2020 Ralph Little <skelband@gmail.com>
|
||||
Copyright (C) 2003 Martijn van Oosterhout <kleptog@svana.org>
|
||||
Copyright (C) 2003 Thomas Soumarmon <thomas.soumarmon@cogitae.net>
|
||||
Copyright (c) 2003 Henning Meier-Geinitz, <henning@meier-geinitz.de>
|
||||
|
@ -149,11 +150,137 @@ SetLamp (THWParams * pHWParams, int fLampOn)
|
|||
if (fLampOn)
|
||||
{
|
||||
if (WriteByte (pHWParams->iXferHandle, 0x0000, 0x01) == 0)
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
HP5400_SANE_STATIC
|
||||
int
|
||||
GetSensors(THWParams * pHWParams, uint16_t *sensorMap)
|
||||
{
|
||||
/*
|
||||
* Read until we get 0.
|
||||
* Max 10 iterations for safety.
|
||||
*
|
||||
*/
|
||||
uint16_t thisSensorMap = 0;
|
||||
size_t iterCount = 10;
|
||||
do
|
||||
{
|
||||
if (hp5400_command_read
|
||||
(pHWParams->iXferHandle, CMD_GETSENSORS, sizeof (uint16_t), &thisSensorMap) < 0)
|
||||
{
|
||||
HP5400_DBG (DBG_MSG, "failed to read sensors\n");
|
||||
return -1;
|
||||
}
|
||||
*sensorMap |= thisSensorMap;
|
||||
} while (iterCount-- && (thisSensorMap > 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HP5400_SANE_STATIC
|
||||
int
|
||||
GetPanelInfo (THWParams * pHWParams, TPanelInfo *panelInfo)
|
||||
{
|
||||
struct PanelInfo info;
|
||||
if (hp5400_command_read (pHWParams->iXferHandle, CMD_READPANEL,
|
||||
sizeof(info), &info) < 0)
|
||||
{
|
||||
HP5400_DBG (DBG_MSG, "failed to read panel info\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
panelInfo->copycount = (SANE_Word)info.copycount;
|
||||
panelInfo->bwcolour = (SANE_Word)info.bwcolour;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HP5400_SANE_STATIC
|
||||
int
|
||||
SetCopyCount(THWParams * pHWParams, SANE_Word copyCount)
|
||||
{
|
||||
|
||||
/*
|
||||
* I don't know what most of these things are but it is
|
||||
* necessary to send something sane otherwise we get an error from the scanner.
|
||||
* I got these settings from a USB trace.
|
||||
* Hopefully, we will learn what it is all about at some point
|
||||
* and hopefully it doesn't screw with other settings.
|
||||
*
|
||||
*/
|
||||
uint8_t packetImage[] = {0x02, 0x06, 0x32, 0x01,
|
||||
0xf2, 0x40, 0x16, 0x01,
|
||||
0x7b, 0x41, 0x16, 0x01,
|
||||
0xdc, 0x06, 0x32, 0x01,
|
||||
0xd7, 0x5b, 0x16, 0x01,
|
||||
0xac, 0x06, 0x32, 0x01,
|
||||
0xf8, 0xd7, 0x18, 0x01,
|
||||
0xd8, 0x06, 0x32, 0x01,
|
||||
0x2c, 0xf3, 0x12, 0x00,
|
||||
0x70, 0x8d, 0x18, 0x01,
|
||||
0x7b, 0x00, 0x00, 0x00};
|
||||
|
||||
struct PanelInfo workingInfo;
|
||||
(void)memcpy(&workingInfo, packetImage, sizeof(workingInfo));
|
||||
|
||||
workingInfo.copycount = (uint8_t)copyCount;
|
||||
|
||||
if (hp5400_command_write (pHWParams->iXferHandle, CMD_WRITEPANEL,
|
||||
sizeof(workingInfo), &workingInfo) < 0)
|
||||
{
|
||||
HP5400_DBG (DBG_MSG, "failed to write panel info\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HP5400_SANE_STATIC
|
||||
int
|
||||
SetColourBW(THWParams * pHWParams, SANE_Word colourBW)
|
||||
{
|
||||
|
||||
/*
|
||||
* I don't know what most of these things are but it is
|
||||
* necessary to send something sane otherwise we get an error from the scanner.
|
||||
* I got these settings from a USB trace.
|
||||
* Hopefully, we will learn what it is all about at some point
|
||||
* and hopefully it doesn't screw with other settings.
|
||||
*
|
||||
*/
|
||||
uint8_t packetImage[] = {0x03, 0x06, 0x32, 0x01,
|
||||
0xf2, 0x40, 0x16, 0x01,
|
||||
0x7b, 0x41, 0x16, 0x01,
|
||||
0xdc, 0x06, 0x32, 0x01,
|
||||
0xd7, 0x5b, 0x16, 0x01,
|
||||
0xac, 0x06, 0x32, 0x01,
|
||||
0xf8, 0xd7, 0x18, 0x01,
|
||||
0xd8, 0x06, 0x32, 0x01,
|
||||
0x68, 0xf5, 0x12, 0x00,
|
||||
0x70, 0x8d, 0x18, 0x01,
|
||||
0x7b, 0x00, 0x00, 0x00};
|
||||
|
||||
struct PanelInfo workingInfo;
|
||||
(void)memcpy(&workingInfo, packetImage, sizeof(workingInfo));
|
||||
|
||||
workingInfo.bwcolour = (uint8_t)colourBW;
|
||||
|
||||
if (hp5400_command_write (pHWParams->iXferHandle, CMD_WRITEPANEL,
|
||||
sizeof(workingInfo), &workingInfo) < 0)
|
||||
{
|
||||
HP5400_DBG (DBG_MSG, "failed to write panel info\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HP5400_SANE_STATIC
|
||||
int
|
||||
WarmupLamp (int iHandle)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define _HP5400_INTERNAL_H_
|
||||
|
||||
/* sane - Scanner Access Now Easy.
|
||||
Copyright (C) 2020 Ralph Little <skelband@gmail.com>
|
||||
(C) 2003 Thomas Soumarmon <thomas.soumarmon@cogitae.net>
|
||||
(c) 2003 Martijn van Oosterhout, kleptog@svana.org
|
||||
(c) 2002 Bertrik Sikken, bertrik@zonnet.nl
|
||||
|
@ -73,6 +74,9 @@
|
|||
#define CMD_SCANREQUEST 0x2505 /* This is for previews */
|
||||
#define CMD_SCANREQUEST2 0x2500 /* This is for real scans */
|
||||
#define CMD_SCANRESPONSE 0x3400
|
||||
#define CMD_GETSENSORS 0x2000
|
||||
#define CMD_READPANEL 0x2100 // Reads info from the scanner. BW/Col + Copy Count. Others, not sure.
|
||||
#define CMD_WRITEPANEL 0x2200 // Ditto for setting.
|
||||
|
||||
/* Testing stuff to make it work */
|
||||
#define CMD_SETDPI 0x1500 /* ??? */
|
||||
|
@ -130,11 +134,40 @@ PACKED;
|
|||
|
||||
struct ScanResponse
|
||||
{
|
||||
uint16_t x1; /* Usually 0x0000 or 0x4000 */
|
||||
uint32_t transfersize; /* Number of bytes to be transferred */
|
||||
uint32_t xsize; /* Shape of returned bitmap */
|
||||
uint16_t ysize; /* Why does the X get more bytes? */
|
||||
uint16_t pad[2]; /* Zero padding to 16 bytes??? */
|
||||
uint16_t x1; /* Usually 0x0000 or 0x4000 */
|
||||
uint32_t transfersize; /* Number of bytes to be transferred */
|
||||
uint32_t xsize; /* Shape of returned bitmap */
|
||||
uint16_t ysize; /* Why does the X get more bytes? */
|
||||
uint16_t pad[2]; /* Zero padding to 16 bytes??? */
|
||||
}
|
||||
PACKED;
|
||||
|
||||
/*
|
||||
* Note: this is the structure of the response we get from CMD_READPANEL.
|
||||
* We only know about two items for the moment. The rest will be ignored
|
||||
* until we understand it better.
|
||||
*
|
||||
* 44 bytes in total.
|
||||
*
|
||||
* Since we don't know what the other things mean, I will assume that they
|
||||
* mean the same things for Get and SET. For SET, we will have to GET, change
|
||||
* what we wish change and SET it back otherwise goodness knows what evil
|
||||
* we will unleash.
|
||||
*
|
||||
* Note that for setting, different values in the buffer seem to apply betwen the copy count
|
||||
* and the colour/BW switch setting. I don't know what that means at the moment.
|
||||
*
|
||||
* I'm calling it PanelInfo because I can't think of anything better.
|
||||
* That may change as the other values are revealed.
|
||||
*
|
||||
*/
|
||||
struct PanelInfo
|
||||
{
|
||||
uint32_t unknown1[10];
|
||||
uint8_t unknown2;
|
||||
uint8_t copycount; // 0..99 from the LCD display.
|
||||
uint8_t bwcolour; // 1 or 2 from the Colour/BW leds.
|
||||
uint8_t unknown3;
|
||||
}
|
||||
PACKED;
|
||||
|
||||
|
@ -156,6 +189,22 @@ HP5400_SANE_STATIC
|
|||
int
|
||||
SetLamp (THWParams * pHWParams, int fLampOn);
|
||||
|
||||
HP5400_SANE_STATIC
|
||||
int
|
||||
GetSensors (THWParams * pHWParams, uint16_t *sensorMap);
|
||||
|
||||
HP5400_SANE_STATIC
|
||||
int
|
||||
GetPanelInfo (THWParams * pHWParams, TPanelInfo *panelInfo);
|
||||
|
||||
HP5400_SANE_STATIC
|
||||
int
|
||||
SetCopyCount(THWParams * pHWParams, SANE_Word copyCount);
|
||||
|
||||
HP5400_SANE_STATIC
|
||||
int
|
||||
SetColourBW(THWParams * pHWParams, SANE_Word colourBW);
|
||||
|
||||
HP5400_SANE_STATIC
|
||||
int
|
||||
WarmupLamp (int iHandle);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* sane - Scanner Access Now Easy.
|
||||
Copyright (C) 2020 Ralph Little <skelband@gmail.com>
|
||||
Copyright (C) 2003 Martijn van Oosterhout <kleptog@svana.org>
|
||||
Copyright (C) 2003 Thomas Soumarmon <thomas.soumarmon@cogitae.net>
|
||||
|
||||
|
@ -71,28 +72,6 @@
|
|||
|
||||
#include "hp5400.h"
|
||||
|
||||
/* includes for data transfer methods */
|
||||
#include "hp5400.h"
|
||||
|
||||
#ifdef STANDALONE
|
||||
#include "hp5400_scanner.h"
|
||||
#endif
|
||||
|
||||
#if defined(LINUX_USB_SUPPORT)
|
||||
#include "hp5400_linux.c"
|
||||
#endif
|
||||
#if defined(USCANNER_SUPPORT)
|
||||
#include "hp5400_uscanner.c"
|
||||
#endif
|
||||
#if defined(LIBUSB_SUPPORT)
|
||||
#include "hp5400_libusb.c"
|
||||
#endif
|
||||
#if defined(LIBIEEE1284_SUPPORT)
|
||||
#include "hp5400_ieee1284.c"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* other definitions */
|
||||
#ifndef min
|
||||
#define min(A,B) (((A)<(B)) ? (A) : (B))
|
||||
|
@ -115,30 +94,91 @@ typedef enum
|
|||
{
|
||||
optCount = 0,
|
||||
|
||||
optGroupGeometry,
|
||||
optTLX, optTLY, optBRX, optBRY,
|
||||
optDPI,
|
||||
|
||||
optGroupImage,
|
||||
optGroupGeometry,
|
||||
optTLX, optTLY, optBRX, optBRY,
|
||||
|
||||
optGroupEnhancement,
|
||||
|
||||
optGammaTableRed, /* Gamma Tables */
|
||||
optGammaTableGreen,
|
||||
optGammaTableBlue,
|
||||
|
||||
optGroupSensors,
|
||||
|
||||
optSensorScanTo,
|
||||
optSensorWeb,
|
||||
optSensorReprint,
|
||||
optSensorEmail,
|
||||
optSensorCopy,
|
||||
optSensorMoreOptions,
|
||||
optSensorCancel,
|
||||
optSensorPowerSave,
|
||||
optSensorCopiesUp,
|
||||
optSensorCopiesDown,
|
||||
optSensorColourBW,
|
||||
|
||||
optSensorColourBWState,
|
||||
optSensorCopyCount,
|
||||
|
||||
// Unsupported as yet.
|
||||
//optGroupMisc,
|
||||
//optLamp,
|
||||
//optCalibrate,
|
||||
|
||||
optLast, /* Disable the offset code */
|
||||
|
||||
optGroupMisc,
|
||||
optOffsetX, optOffsetY
|
||||
|
||||
|
||||
/* put temporarily disabled options here after optLast */
|
||||
/*
|
||||
optLamp,
|
||||
*/
|
||||
|
||||
}
|
||||
EOptionIndex;
|
||||
|
||||
/*
|
||||
* Array mapping (optSensor* - optGroupSensors - 1) to the bit mask of the
|
||||
* corresponding sensor bit that we get from the scanner.
|
||||
* All sensor bits are reported as a complete 16-bit word with individual bits set
|
||||
* to indicate that the sensor has been activated.
|
||||
* They seem to be latched so that they are picked up on next query and a number
|
||||
* of bits can be set in any one query.
|
||||
*
|
||||
*/
|
||||
|
||||
#define SENSOR_BIT_SCAN 0x0400
|
||||
#define SENSOR_BIT_WEB 0x0200
|
||||
#define SENSOR_BIT_REPRINT 0x0002
|
||||
#define SENSOR_BIT_EMAIL 0x0080
|
||||
#define SENSOR_BIT_COPY 0x0040
|
||||
#define SENSOR_BIT_MOREOPTIONS 0x0004
|
||||
#define SENSOR_BIT_CANCEL 0x0100
|
||||
#define SENSOR_BIT_POWERSAVE 0x2000
|
||||
#define SENSOR_BIT_COPIESUP 0x0008
|
||||
#define SENSOR_BIT_COPIESDOWN 0x0020
|
||||
#define SENSOR_BIT_COLOURBW 0x0010
|
||||
|
||||
|
||||
uint16_t sensorMaskMap[] =
|
||||
{
|
||||
SENSOR_BIT_SCAN,
|
||||
SENSOR_BIT_WEB,
|
||||
SENSOR_BIT_REPRINT,
|
||||
SENSOR_BIT_EMAIL,
|
||||
SENSOR_BIT_COPY,
|
||||
SENSOR_BIT_MOREOPTIONS,
|
||||
SENSOR_BIT_CANCEL,
|
||||
|
||||
// Special buttons.
|
||||
// These affect local machine settings, but we can still detect them being pressed.
|
||||
SENSOR_BIT_POWERSAVE,
|
||||
SENSOR_BIT_COPIESUP,
|
||||
SENSOR_BIT_COPIESDOWN,
|
||||
SENSOR_BIT_COLOURBW,
|
||||
|
||||
// Extra entries to make the array up to the 16 possible bits.
|
||||
0x0000, // Unused
|
||||
0x0000, // Unused
|
||||
0x0000, // Unused
|
||||
0x0000, // Unused
|
||||
0x0000 // Unused
|
||||
};
|
||||
|
||||
typedef union
|
||||
{
|
||||
SANE_Word w;
|
||||
|
@ -165,6 +205,8 @@ typedef struct
|
|||
|
||||
int fScanning; /* TRUE if actively scanning */
|
||||
int fCanceled;
|
||||
|
||||
uint16_t sensorMap; /* Contains the current unreported sensor bits. */
|
||||
}
|
||||
TScanner;
|
||||
|
||||
|
@ -191,18 +233,19 @@ static const SANE_Device **_pSaneDevList = 0;
|
|||
|
||||
/* option constraints */
|
||||
static const SANE_Range rangeGammaTable = {0, 65535, 1};
|
||||
static const SANE_Range rangeCopyCountTable = {0, 99, 1};
|
||||
static SANE_String_Const modeSwitchList[] = {
|
||||
SANE_VALUE_SCAN_MODE_COLOR,
|
||||
SANE_VALUE_SCAN_MODE_GRAY,
|
||||
NULL
|
||||
};
|
||||
#ifdef SUPPORT_2400_DPI
|
||||
static const SANE_Int setResolutions[] = {6, 75, 150, 300, 600, 1200, 2400};
|
||||
#else
|
||||
static const SANE_Int setResolutions[] = {5, 75, 150, 300, 600, 1200};
|
||||
#endif
|
||||
static const SANE_Range rangeXmm = {0, 220, 1};
|
||||
static const SANE_Range rangeYmm = {0, 300, 1};
|
||||
static const SANE_Range rangeXoffset = {0, 20, 1};
|
||||
static const SANE_Range rangeYoffset = {0, 70, 1};
|
||||
static const SANE_Int offsetX = 5;
|
||||
static const SANE_Int offsetY = 52;
|
||||
|
||||
static const SANE_Range rangeXmm = {0, 216, 1};
|
||||
static const SANE_Range rangeYmm = {0, 297, 1};
|
||||
|
||||
static void _InitOptions(TScanner *s)
|
||||
{
|
||||
|
@ -248,8 +291,22 @@ static void _InitOptions(TScanner *s)
|
|||
pVal->w = (SANE_Word)optLast;
|
||||
break;
|
||||
|
||||
case optDPI:
|
||||
pDesc->name = SANE_NAME_SCAN_RESOLUTION;
|
||||
pDesc->title = SANE_TITLE_SCAN_RESOLUTION;
|
||||
pDesc->desc = SANE_DESC_SCAN_RESOLUTION;
|
||||
pDesc->unit = SANE_UNIT_DPI;
|
||||
pDesc->constraint_type = SANE_CONSTRAINT_WORD_LIST;
|
||||
pDesc->constraint.word_list = setResolutions;
|
||||
pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||||
pVal->w = setResolutions[1];
|
||||
break;
|
||||
|
||||
//---------------------------------
|
||||
case optGroupGeometry:
|
||||
pDesc->title = "Geometry";
|
||||
pDesc->name = SANE_NAME_GEOMETRY;
|
||||
pDesc->title = SANE_TITLE_GEOMETRY;
|
||||
pDesc->desc = SANE_DESC_GEOMETRY;
|
||||
pDesc->type = SANE_TYPE_GROUP;
|
||||
pDesc->size = 0;
|
||||
break;
|
||||
|
@ -262,7 +319,7 @@ static void _InitOptions(TScanner *s)
|
|||
pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
pDesc->constraint.range = &rangeXmm;
|
||||
pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||||
pVal->w = rangeXmm.min + offsetX;
|
||||
pVal->w = rangeXmm.min;
|
||||
break;
|
||||
|
||||
case optTLY:
|
||||
|
@ -273,7 +330,7 @@ static void _InitOptions(TScanner *s)
|
|||
pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
pDesc->constraint.range = &rangeYmm;
|
||||
pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||||
pVal->w = rangeYmm.min + offsetY;
|
||||
pVal->w = rangeYmm.min;
|
||||
break;
|
||||
|
||||
case optBRX:
|
||||
|
@ -284,7 +341,7 @@ static void _InitOptions(TScanner *s)
|
|||
pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
pDesc->constraint.range = &rangeXmm;
|
||||
pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||||
pVal->w = rangeXmm.max + offsetX;
|
||||
pVal->w = rangeXmm.max;
|
||||
break;
|
||||
|
||||
case optBRY:
|
||||
|
@ -295,22 +352,14 @@ static void _InitOptions(TScanner *s)
|
|||
pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
pDesc->constraint.range = &rangeYmm;
|
||||
pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||||
pVal->w = rangeYmm.max + offsetY;
|
||||
pVal->w = rangeYmm.max;
|
||||
break;
|
||||
|
||||
case optDPI:
|
||||
pDesc->name = SANE_NAME_SCAN_RESOLUTION;
|
||||
pDesc->title = SANE_TITLE_SCAN_RESOLUTION;
|
||||
pDesc->desc = SANE_DESC_SCAN_RESOLUTION;
|
||||
pDesc->unit = SANE_UNIT_DPI;
|
||||
pDesc->constraint_type = SANE_CONSTRAINT_WORD_LIST;
|
||||
pDesc->constraint.word_list = setResolutions;
|
||||
pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||||
pVal->w = setResolutions[1];
|
||||
break;
|
||||
|
||||
case optGroupImage:
|
||||
pDesc->title = SANE_I18N("Image");
|
||||
//---------------------------------
|
||||
case optGroupEnhancement:
|
||||
pDesc->name = SANE_NAME_ENHANCEMENT;
|
||||
pDesc->title = SANE_TITLE_ENHANCEMENT;
|
||||
pDesc->desc = SANE_DESC_ENHANCEMENT;
|
||||
pDesc->type = SANE_TYPE_GROUP;
|
||||
pDesc->size = 0;
|
||||
break;
|
||||
|
@ -348,34 +397,130 @@ static void _InitOptions(TScanner *s)
|
|||
pVal->wa = s->aGammaTableB;
|
||||
break;
|
||||
|
||||
//---------------------------------
|
||||
case optGroupSensors:
|
||||
pDesc->name = SANE_NAME_SENSORS;
|
||||
pDesc->title = SANE_TITLE_SENSORS;
|
||||
pDesc->type = SANE_TYPE_GROUP;
|
||||
pDesc->desc = SANE_DESC_SENSORS;
|
||||
pDesc->size = 0;
|
||||
break;
|
||||
|
||||
case optSensorScanTo:
|
||||
pDesc->name = SANE_NAME_SCAN;
|
||||
pDesc->title = SANE_TITLE_SCAN;
|
||||
pDesc->desc = SANE_DESC_SCAN;
|
||||
pDesc->type = SANE_TYPE_BOOL;
|
||||
pDesc->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
|
||||
break;
|
||||
|
||||
case optSensorWeb:
|
||||
pDesc->name = SANE_I18N("web");
|
||||
pDesc->title = SANE_I18N("Share-To-Web button");
|
||||
pDesc->desc = SANE_I18N("Scan an image and send it on the web");
|
||||
pDesc->type = SANE_TYPE_BOOL;
|
||||
pDesc->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
|
||||
break;
|
||||
|
||||
case optSensorReprint:
|
||||
pDesc->name = SANE_I18N("reprint");
|
||||
pDesc->title = SANE_I18N("Reprint Photos button");
|
||||
pDesc->desc = SANE_I18N("Button for reprinting photos");
|
||||
pDesc->type = SANE_TYPE_BOOL;
|
||||
pDesc->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
|
||||
break;
|
||||
|
||||
case optSensorEmail:
|
||||
pDesc->name = SANE_NAME_EMAIL;
|
||||
pDesc->title = SANE_TITLE_EMAIL;
|
||||
pDesc->desc = SANE_DESC_EMAIL;
|
||||
pDesc->type = SANE_TYPE_BOOL;
|
||||
pDesc->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
|
||||
break;
|
||||
|
||||
case optSensorCopy:
|
||||
pDesc->name = SANE_NAME_COPY;
|
||||
pDesc->title = SANE_TITLE_COPY;
|
||||
pDesc->desc = SANE_DESC_COPY;
|
||||
pDesc->type = SANE_TYPE_BOOL;
|
||||
pDesc->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
|
||||
break;
|
||||
|
||||
case optSensorMoreOptions:
|
||||
pDesc->name = SANE_I18N("more-options");
|
||||
pDesc->title = SANE_I18N("More Options button");
|
||||
pDesc->desc = SANE_I18N("Button for additional options/configuration");
|
||||
pDesc->type = SANE_TYPE_BOOL;
|
||||
pDesc->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
|
||||
break;
|
||||
|
||||
case optSensorCancel:
|
||||
pDesc->name = SANE_NAME_CANCEL;
|
||||
pDesc->title = SANE_TITLE_CANCEL;
|
||||
pDesc->desc = SANE_DESC_CANCEL;
|
||||
pDesc->type = SANE_TYPE_BOOL;
|
||||
pDesc->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
|
||||
break;
|
||||
|
||||
case optSensorPowerSave:
|
||||
pDesc->name = SANE_I18N("power-save");
|
||||
pDesc->title = SANE_I18N("Power Save button");
|
||||
pDesc->desc = SANE_I18N("Puts the scanner in an energy-conservation mode");
|
||||
pDesc->type = SANE_TYPE_BOOL;
|
||||
pDesc->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
|
||||
break;
|
||||
|
||||
case optSensorCopiesUp:
|
||||
pDesc->name = SANE_I18N("copies-up");
|
||||
pDesc->title = SANE_I18N("Increase Copies button");
|
||||
pDesc->desc = SANE_I18N("Increase the number of copies");
|
||||
pDesc->type = SANE_TYPE_BOOL;
|
||||
pDesc->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
|
||||
break;
|
||||
|
||||
case optSensorCopiesDown:
|
||||
pDesc->name = SANE_I18N("copies-down");
|
||||
pDesc->title = SANE_I18N("Decrease Copies button");
|
||||
pDesc->desc = SANE_I18N("Decrease the number of copies");
|
||||
pDesc->type = SANE_TYPE_BOOL;
|
||||
pDesc->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
|
||||
break;
|
||||
|
||||
case optSensorColourBW:
|
||||
pDesc->name = SANE_I18N("color-bw");
|
||||
pDesc->title = SANE_I18N("Select color/BW button");
|
||||
pDesc->desc = SANE_I18N("Alternates between color and black/white scanning");
|
||||
pDesc->type = SANE_TYPE_BOOL;
|
||||
pDesc->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
|
||||
break;
|
||||
|
||||
case optSensorColourBWState:
|
||||
pDesc->name = SANE_I18N("color-bw-state");
|
||||
pDesc->title = SANE_I18N("Read color/BW button state");
|
||||
pDesc->desc = SANE_I18N("Reads state of BW/colour panel setting");
|
||||
pDesc->type = SANE_TYPE_STRING;
|
||||
pDesc->constraint_type = SANE_CONSTRAINT_STRING_LIST;
|
||||
pDesc->constraint.string_list = modeSwitchList;
|
||||
pDesc->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
|
||||
break;
|
||||
|
||||
case optSensorCopyCount:
|
||||
pDesc->name = SANE_I18N("copies-count");
|
||||
pDesc->title = SANE_I18N("Read copy count value");
|
||||
pDesc->desc = SANE_I18N("Reads state of copy count panel setting");
|
||||
pDesc->type = SANE_TYPE_INT;
|
||||
pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
pDesc->constraint.range = &rangeCopyCountTable;
|
||||
pDesc->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case optGroupMisc:
|
||||
pDesc->title = SANE_I18N("Miscellaneous");
|
||||
pDesc->type = SANE_TYPE_GROUP;
|
||||
pDesc->size = 0;
|
||||
break;
|
||||
|
||||
case optOffsetX:
|
||||
pDesc->title = SANE_I18N("offset X");
|
||||
pDesc->desc = SANE_I18N("Hardware internal X position of the scanning area.");
|
||||
pDesc->unit = SANE_UNIT_MM;
|
||||
pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
pDesc->constraint.range = &rangeXoffset;
|
||||
pDesc->cap = SANE_CAP_SOFT_SELECT;
|
||||
pVal->w = offsetX;
|
||||
break;
|
||||
|
||||
case optOffsetY:
|
||||
pDesc->title = SANE_I18N("offset Y");
|
||||
pDesc->desc = SANE_I18N("Hardware internal Y position of the scanning area.");
|
||||
pDesc->unit = SANE_UNIT_MM;
|
||||
pDesc->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
pDesc->constraint.range = &rangeYoffset;
|
||||
pDesc->cap = SANE_CAP_SOFT_SELECT;
|
||||
pVal->w = offsetY;
|
||||
break;
|
||||
|
||||
|
||||
#if 0
|
||||
case optLamp:
|
||||
pDesc->name = "lamp";
|
||||
pDesc->title = SANE_I18N("Lamp status");
|
||||
|
@ -385,8 +530,7 @@ static void _InitOptions(TScanner *s)
|
|||
/* switch the lamp on when starting for first the time */
|
||||
pVal->w = SANE_TRUE;
|
||||
break;
|
||||
#endif
|
||||
#if 0
|
||||
|
||||
case optCalibrate:
|
||||
pDesc->name = "calibrate";
|
||||
pDesc->title = SANE_I18N("Calibrate");
|
||||
|
@ -467,7 +611,7 @@ sane_init (SANE_Int * piVersion, SANE_Auth_Callback pfnAuth)
|
|||
SANE_String_Const proper_str;
|
||||
int nline = 0;
|
||||
|
||||
/* prevent compiler from complaing about unused parameters */
|
||||
/* prevent compiler from complaining about unused parameters */
|
||||
pfnAuth = pfnAuth;
|
||||
|
||||
strcpy(usb_devfile, "/dev/usb/scanner0");
|
||||
|
@ -531,7 +675,6 @@ sane_init (SANE_Int * piVersion, SANE_Auth_Callback pfnAuth)
|
|||
*piVersion = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD);
|
||||
}
|
||||
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
@ -694,7 +837,7 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action,
|
|||
/* Get options of type SANE_Word */
|
||||
case optBRX:
|
||||
case optTLX:
|
||||
*(SANE_Word *) pVal = s->aValues[n].w; /* Not needed anymore - s->aValues[optOffsetX].w; */
|
||||
*(SANE_Word *) pVal = s->aValues[n].w;
|
||||
HP5400_DBG (DBG_MSG,
|
||||
"sane_control_option: SANE_ACTION_GET_VALUE %d = %d\n", n,
|
||||
*(SANE_Word *) pVal);
|
||||
|
@ -702,14 +845,12 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action,
|
|||
|
||||
case optBRY:
|
||||
case optTLY:
|
||||
*(SANE_Word *) pVal = s->aValues[n].w; /* Not needed anymore - - s->aValues[optOffsetY].w; */
|
||||
*(SANE_Word *) pVal = s->aValues[n].w;
|
||||
HP5400_DBG (DBG_MSG,
|
||||
"sane_control_option: SANE_ACTION_GET_VALUE %d = %d\n", n,
|
||||
*(SANE_Word *) pVal);
|
||||
break;
|
||||
|
||||
case optOffsetX:
|
||||
case optOffsetY:
|
||||
case optCount:
|
||||
case optDPI:
|
||||
HP5400_DBG (DBG_MSG,
|
||||
|
@ -726,14 +867,94 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action,
|
|||
memcpy (pVal, s->aValues[n].wa, s->aOptions[n].size);
|
||||
break;
|
||||
|
||||
case optSensorScanTo:
|
||||
case optSensorWeb:
|
||||
case optSensorReprint:
|
||||
case optSensorEmail:
|
||||
case optSensorCopy:
|
||||
case optSensorMoreOptions:
|
||||
case optSensorCancel:
|
||||
case optSensorPowerSave:
|
||||
case optSensorCopiesUp:
|
||||
case optSensorCopiesDown:
|
||||
case optSensorColourBW:
|
||||
{
|
||||
HP5400_DBG (DBG_MSG, "Reading sensor state\n");
|
||||
|
||||
uint16_t sensorMap;
|
||||
if (GetSensors(&s->HWParams, &sensorMap) != 0)
|
||||
{
|
||||
HP5400_DBG (DBG_ERR,
|
||||
"sane_control_option: SANE_ACTION_SET_VALUE could not retrieve sensors\n");
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
|
||||
}
|
||||
|
||||
HP5400_DBG (DBG_MSG, "Sensor state=%x\n", sensorMap);
|
||||
|
||||
// Add read flags to what we already have so that we can report them when requested.
|
||||
s->sensorMap |= sensorMap;
|
||||
|
||||
// Look up the mask based on the option number.
|
||||
uint16_t mask = sensorMaskMap[n - optGroupSensors - 1];
|
||||
*(SANE_Word *) pVal = (s->sensorMap & mask)? 1:0;
|
||||
s->sensorMap &= ~mask;
|
||||
break;
|
||||
}
|
||||
|
||||
case optSensorCopyCount:
|
||||
{
|
||||
HP5400_DBG (DBG_MSG, "Reading copy count\n");
|
||||
|
||||
TPanelInfo panelInfo;
|
||||
if (GetPanelInfo(&s->HWParams, &panelInfo) != 0)
|
||||
{
|
||||
HP5400_DBG (DBG_ERR,
|
||||
"sane_control_option: SANE_ACTION_SET_VALUE could not retrieve panel info\n");
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
|
||||
}
|
||||
|
||||
HP5400_DBG (DBG_MSG, "Copy count setting=%u\n", panelInfo.copycount);
|
||||
*(SANE_Word *) pVal = panelInfo.copycount;
|
||||
break;
|
||||
}
|
||||
|
||||
case optSensorColourBWState:
|
||||
{
|
||||
HP5400_DBG (DBG_MSG, "Reading BW/Colour setting\n");
|
||||
|
||||
TPanelInfo panelInfo;
|
||||
if (GetPanelInfo(&s->HWParams, &panelInfo) != 0)
|
||||
{
|
||||
HP5400_DBG (DBG_ERR,
|
||||
"sane_control_option: SANE_ACTION_SET_VALUE could not retrieve panel info\n");
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
|
||||
}
|
||||
|
||||
HP5400_DBG (DBG_MSG, "BW/Colour setting=%u\n", panelInfo.bwcolour);
|
||||
|
||||
// Just for safety:
|
||||
if (panelInfo.bwcolour < 1)
|
||||
{
|
||||
panelInfo.bwcolour = 1;
|
||||
}
|
||||
else if (panelInfo.bwcolour > 2)
|
||||
{
|
||||
panelInfo.bwcolour = 2;
|
||||
}
|
||||
(void)strcpy((SANE_String)pVal, modeSwitchList[panelInfo.bwcolour - 1]);
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Get options of type SANE_Bool */
|
||||
case optLamp:
|
||||
GetLamp (&s->HWParams, &fLampIsOn);
|
||||
*(SANE_Bool *) pVal = fLampIsOn;
|
||||
break;
|
||||
#endif
|
||||
#if 0
|
||||
|
||||
case optCalibrate:
|
||||
/* although this option has nothing to read,
|
||||
it's added here to avoid a warning when running scanimage --help */
|
||||
|
@ -761,26 +982,70 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action,
|
|||
|
||||
case optBRX:
|
||||
case optTLX:
|
||||
info |= SANE_INFO_RELOAD_PARAMS;
|
||||
s->ScanParams.iLines = 0; /* Forget actual image settings */
|
||||
s->aValues[n].w = *(SANE_Word *) pVal; /* Not needed anymore - + s->aValues[optOffsetX].w; */
|
||||
break;
|
||||
{
|
||||
// Check against legal values.
|
||||
SANE_Word value = *(SANE_Word *) pVal;
|
||||
if ((value < s->aOptions[n].constraint.range->min) ||
|
||||
(value > s->aOptions[n].constraint.range->max))
|
||||
{
|
||||
HP5400_DBG (DBG_ERR,
|
||||
"sane_control_option: SANE_ACTION_SET_VALUE out of range X value\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
case optBRY:
|
||||
case optTLY:
|
||||
info |= SANE_INFO_RELOAD_PARAMS;
|
||||
s->ScanParams.iLines = 0; /* Forget actual image settings */
|
||||
s->aValues[n].w = *(SANE_Word *) pVal; /* Not needed anymore - + s->aValues[optOffsetY].w; */
|
||||
break;
|
||||
case optDPI:
|
||||
info |= SANE_INFO_RELOAD_PARAMS;
|
||||
s->ScanParams.iLines = 0; /* Forget actual image settings */
|
||||
#ifdef SUPPORT_2400_DPI
|
||||
(s->aValues[n].w) = *(SANE_Word *) pVal;
|
||||
#else
|
||||
(s->aValues[n].w) = min (1200, *(SANE_Word *) pVal);
|
||||
#endif
|
||||
break;
|
||||
info |= SANE_INFO_RELOAD_PARAMS;
|
||||
s->ScanParams.iLines = 0; /* Forget actual image settings */
|
||||
s->aValues[n].w = value;
|
||||
break;
|
||||
}
|
||||
|
||||
case optBRY:
|
||||
case optTLY:
|
||||
{
|
||||
// Check against legal values.
|
||||
SANE_Word value = *(SANE_Word *) pVal;
|
||||
if ((value < s->aOptions[n].constraint.range->min) ||
|
||||
(value > s->aOptions[n].constraint.range->max))
|
||||
{
|
||||
HP5400_DBG (DBG_ERR,
|
||||
"sane_control_option: SANE_ACTION_SET_VALUE out of range Y value\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
info |= SANE_INFO_RELOAD_PARAMS;
|
||||
s->ScanParams.iLines = 0; /* Forget actual image settings */
|
||||
s->aValues[n].w = value;
|
||||
break;
|
||||
}
|
||||
|
||||
case optDPI:
|
||||
{
|
||||
// Check against legal values.
|
||||
SANE_Word dpiValue = *(SANE_Word *) pVal;
|
||||
|
||||
// First check too large.
|
||||
SANE_Word maxRes = setResolutions[setResolutions[0]];
|
||||
if (dpiValue > maxRes)
|
||||
{
|
||||
dpiValue = maxRes;
|
||||
}
|
||||
else // Check smaller values: if not exact match, pick next higher available.
|
||||
{
|
||||
for (SANE_Int resIdx = 1; resIdx <= setResolutions[0]; resIdx++)
|
||||
{
|
||||
if (dpiValue <= setResolutions[resIdx])
|
||||
{
|
||||
dpiValue = setResolutions[resIdx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info |= SANE_INFO_RELOAD_PARAMS;
|
||||
s->ScanParams.iLines = 0; /* Forget actual image settings */
|
||||
(s->aValues[n].w) = dpiValue;
|
||||
break;
|
||||
}
|
||||
|
||||
case optGammaTableRed:
|
||||
case optGammaTableGreen:
|
||||
|
@ -788,6 +1053,70 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action,
|
|||
HP5400_DBG (DBG_MSG, "Writing gamma table\n");
|
||||
memcpy (s->aValues[n].wa, pVal, s->aOptions[n].size);
|
||||
break;
|
||||
|
||||
case optSensorColourBWState:
|
||||
{
|
||||
SANE_String bwColour = (SANE_String)pVal;
|
||||
SANE_Word bwColourValue;
|
||||
|
||||
if (strcmp(bwColour, SANE_VALUE_SCAN_MODE_COLOR) == 0)
|
||||
{
|
||||
bwColourValue = 1;
|
||||
}
|
||||
else if (strcmp(bwColour, SANE_VALUE_SCAN_MODE_GRAY) == 0)
|
||||
{
|
||||
bwColourValue = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
HP5400_DBG (DBG_ERR,
|
||||
"sane_control_option: SANE_ACTION_SET_VALUE invalid colour/bw mode\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
HP5400_DBG (DBG_MSG, "Setting BW/Colour state=%d\n", bwColourValue);
|
||||
|
||||
/*
|
||||
* Now write it with the other panel settings back to the scanner.
|
||||
*
|
||||
*/
|
||||
if (SetColourBW(&s->HWParams, bwColourValue) != 0)
|
||||
{
|
||||
HP5400_DBG (DBG_ERR,
|
||||
"sane_control_option: SANE_ACTION_SET_VALUE could not set colour/BW mode\n");
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case optSensorCopyCount:
|
||||
{
|
||||
SANE_Word copyCount = *(SANE_Word *) pVal;
|
||||
if (copyCount < 0)
|
||||
{
|
||||
copyCount = 0;
|
||||
}
|
||||
else if (copyCount > 99)
|
||||
{
|
||||
copyCount = 99;
|
||||
}
|
||||
|
||||
HP5400_DBG (DBG_MSG, "Setting Copy Count=%d\n", copyCount);
|
||||
|
||||
/*
|
||||
* Now write it with the other panel settings back to the scanner.
|
||||
*
|
||||
*/
|
||||
if (SetCopyCount(&s->HWParams, copyCount) != 0)
|
||||
{
|
||||
HP5400_DBG (DBG_ERR,
|
||||
"sane_control_option: SANE_ACTION_SET_VALUE could not set copy count\n");
|
||||
return SANE_STATUS_IO_ERROR;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
case optLamp:
|
||||
fVal = *(SANE_Bool *)pVal;
|
||||
|
@ -924,6 +1253,7 @@ sane_start (SANE_Handle h)
|
|||
s->ScanParams.iLinesRead = 0;
|
||||
|
||||
s->fScanning = TRUE;
|
||||
s->fCanceled = FALSE;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
@ -944,6 +1274,11 @@ sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)
|
|||
|
||||
/* nothing has been read for the moment */
|
||||
*len = 0;
|
||||
if (!s->fScanning || s->fCanceled)
|
||||
{
|
||||
HP5400_DBG (DBG_MSG, "sane_read: we're not scanning.\n");
|
||||
return SANE_STATUS_EOF;
|
||||
}
|
||||
|
||||
|
||||
/* if we read all the lines return EOF */
|
||||
|
|
|
@ -32,13 +32,13 @@ convenient lines to paste
|
|||
export SANE_DEBUG_KODAKAIO=20
|
||||
|
||||
for ubuntu prior to 12.10
|
||||
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-avahi --without-api-spec BACKENDS="kodakaio test"
|
||||
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-avahi BACKENDS="kodakaio test"
|
||||
|
||||
for ubuntu 12.10
|
||||
./configure --prefix=/usr --libdir=/usr/lib/i386-linux-gnu --sysconfdir=/etc --localstatedir=/var --enable-avahi --without-api-spec BACKENDS="kodakaio test"
|
||||
./configure --prefix=/usr --libdir=/usr/lib/i386-linux-gnu --sysconfdir=/etc --localstatedir=/var --enable-avahi BACKENDS="kodakaio test"
|
||||
|
||||
for ubuntu 14.10 up to at least 17.04
|
||||
./configure --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu --sysconfdir=/etc --localstatedir=/var --enable-avahi --without-api-spec BACKENDS="kodakaio test"
|
||||
./configure --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu --sysconfdir=/etc --localstatedir=/var --enable-avahi BACKENDS="kodakaio test"
|
||||
|
||||
If you want to use the test backend, for example with sane-troubleshoot, you should enable it in /etc/sane.d/dll.conf
|
||||
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
|
||||
#include "../include/sane/sanei_debug.h"
|
||||
|
||||
/* SANE backend operations, see Sane standard 1.04 documents (sane_dev.pdf)
|
||||
for details */
|
||||
/* SANE backend operations, see SANE Standard for details
|
||||
https://sane-project.gitlab.io/standard/ */
|
||||
|
||||
/* Init the KV-S1025 SANE backend. This function must be called before any other
|
||||
SANE function can be called. */
|
||||
|
|
|
@ -119,8 +119,8 @@ typedef uint32_t uint32_t;
|
|||
/** \name Version of the driver */
|
||||
/**@{*/
|
||||
#define PIXMA_VERSION_MAJOR 0
|
||||
#define PIXMA_VERSION_MINOR 26
|
||||
#define PIXMA_VERSION_BUILD 0
|
||||
#define PIXMA_VERSION_MINOR 27
|
||||
#define PIXMA_VERSION_BUILD 2
|
||||
/**@}*/
|
||||
|
||||
/** \name Error codes */
|
|
@ -39,6 +39,7 @@
|
|||
whether to permit this exception to apply to your modifications.
|
||||
If you do not wish that, delete this exception notice.
|
||||
*/
|
||||
|
||||
#undef BACKEND_NAME
|
||||
#define BACKEND_NAME bjnp
|
||||
|
||||
|
@ -117,6 +118,40 @@ static int bjnp_no_devices = 0;
|
|||
* Private functions
|
||||
*/
|
||||
|
||||
static const struct pixma_config_t *lookup_scanner(const char *makemodel,
|
||||
const struct pixma_config_t *const pixma_devices[])
|
||||
{
|
||||
int i;
|
||||
const struct pixma_config_t *cfg;
|
||||
char *match;
|
||||
|
||||
for (i = 0; pixma_devices[i]; i++)
|
||||
{
|
||||
/* loop through the device classes (mp150, mp730 etc) */
|
||||
for (cfg = pixma_devices[i]; cfg->name; cfg++)
|
||||
{
|
||||
/* loop through devices in class */
|
||||
PDBG( bjnp_dbg( LOG_DEBUG3, "lookup_scanner: Checking for %s in %s\n", makemodel, cfg->model));
|
||||
if ((match = strcasestr (makemodel, cfg->model)) != NULL)
|
||||
{
|
||||
/* possible match found, make sure it is not a partial match */
|
||||
/* MP600 and MP600R are different models! */
|
||||
/* some models contain ranges, so check for a '-' too */
|
||||
|
||||
if ((match[strlen(cfg->model)] == ' ') ||
|
||||
(match[strlen(cfg->model)] == '\0') ||
|
||||
(match[strlen(cfg->model)] == '-'))
|
||||
{
|
||||
PDBG( bjnp_dbg (LOG_DEBUG, "lookup_scanner: Scanner model found: Name %s(%s) matches %s\n", cfg->model, cfg->name, makemodel));
|
||||
return cfg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PDBG( bjnp_dbg (LOG_DEBUG, "lookup_scanner: Scanner model %s not found, giving up!\n", makemodel));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
u8tohex (char *string, const uint8_t *value, int len )
|
||||
{
|
||||
|
@ -1811,16 +1846,15 @@ static void add_scanner(SANE_Int *dev_no,
|
|||
const char *uri,
|
||||
SANE_Status (*attach_bjnp)
|
||||
(SANE_String_Const devname,
|
||||
SANE_String_Const makemodel,
|
||||
SANE_String_Const serial,
|
||||
const struct pixma_config_t *
|
||||
const pixma_devices[]),
|
||||
const struct pixma_config_t *const pixma_devices[])
|
||||
const struct pixma_config_t *cfg),
|
||||
const struct pixma_config_t *const pixma_devices[])
|
||||
|
||||
{
|
||||
char scanner_host[BJNP_HOST_MAX];
|
||||
char serial[BJNP_SERIAL_MAX];
|
||||
char makemodel[BJNP_MODEL_MAX];
|
||||
const struct pixma_config_t *cfg = NULL;
|
||||
|
||||
/* Allocate device structure for scanner */
|
||||
switch (bjnp_allocate_device (uri, dev_no, scanner_host))
|
||||
|
@ -1833,17 +1867,32 @@ static void add_scanner(SANE_Int *dev_no,
|
|||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* inform caller of found scanner
|
||||
*/
|
||||
/*
|
||||
* fetch scanner configuration
|
||||
*/
|
||||
if ((cfg = lookup_scanner(makemodel, pixma_devices)) == (struct pixma_config_t *)NULL)
|
||||
{
|
||||
PDBG (bjnp_dbg (LOG_CRIT, "add_scanner: Scanner %s is not supported, model is unknown! Please report upstream\n", makemodel));
|
||||
break;
|
||||
}
|
||||
|
||||
determine_scanner_serial (scanner_host, device[*dev_no].mac_address, serial);
|
||||
/*
|
||||
* inform caller of found scanner
|
||||
*/
|
||||
|
||||
attach_bjnp (uri, makemodel,
|
||||
serial, pixma_devices);
|
||||
PDBG (bjnp_dbg (LOG_NOTICE, "add_scanner: New scanner added: %s, serial %s, mac address: %s.\n",
|
||||
uri, serial, device[*dev_no].mac_address));
|
||||
determine_scanner_serial (scanner_host, device[*dev_no].mac_address, serial);
|
||||
|
||||
switch (attach_bjnp (uri, serial, cfg))
|
||||
{
|
||||
case SANE_STATUS_GOOD:
|
||||
PDBG (bjnp_dbg (LOG_NOTICE, "add_scanner: New scanner added: %s, serial %s, mac address: %s.\n",
|
||||
uri, serial, device[*dev_no].mac_address));
|
||||
break;
|
||||
default:
|
||||
PDBG (bjnp_dbg (LOG_CRIT, "add_scanner: unexpected error (out of memory?), adding %s\n", makemodel));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case BJNP_STATUS_ALREADY_ALLOCATED:
|
||||
PDBG (bjnp_dbg (LOG_NOTICE, "add_scanner: Scanner at %s was added before, good!\n",
|
||||
|
@ -1898,10 +1947,7 @@ int add_timeout_to_uri(char *uri, int timeout, int max_len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Public functions
|
||||
*/
|
||||
/** Public functions **/
|
||||
|
||||
/** Initialize sanei_bjnp.
|
||||
*
|
||||
|
@ -1926,11 +1972,9 @@ sanei_bjnp_init (void)
|
|||
extern SANE_Status
|
||||
sanei_bjnp_find_devices (const char **conf_devices,
|
||||
SANE_Status (*attach_bjnp)
|
||||
(SANE_String_Const devname,
|
||||
SANE_String_Const makemodel,
|
||||
SANE_String_Const serial,
|
||||
const struct pixma_config_t *
|
||||
const pixma_devices[]),
|
||||
(SANE_String_Const devname,
|
||||
SANE_String_Const serial,
|
||||
const struct pixma_config_t *cfg),
|
||||
const struct pixma_config_t *const pixma_devices[])
|
||||
{
|
||||
int numbytes = 0;
|
|
@ -81,12 +81,10 @@ extern void sanei_bjnp_init (void);
|
|||
extern SANE_Status
|
||||
sanei_bjnp_find_devices (const char **conf_devices,
|
||||
SANE_Status (*attach_bjnp)
|
||||
(SANE_String_Const devname,
|
||||
SANE_String_Const makemodel,
|
||||
SANE_String_Const serial,
|
||||
const struct pixma_config_t *
|
||||
const pixma_devices[]),
|
||||
const struct pixma_config_t *const pixma_devices[]);
|
||||
(SANE_String_Const devname,
|
||||
SANE_String_Const serial,
|
||||
const struct pixma_config_t *cfg),
|
||||
const struct pixma_config_t *const pixma_devices[]);
|
||||
|
||||
/** Open a BJNP device.
|
||||
*
|
|
@ -119,6 +119,7 @@
|
|||
#define MF420_PID 0x27f1
|
||||
#define MF260_PID 0x27f4
|
||||
#define MF740_PID 0x27fb
|
||||
#define MF743_PID 0x27fc
|
||||
#define MF640_PID 0x27fe
|
||||
#define MF645_PID 0x27fd
|
||||
|
||||
|
@ -972,11 +973,12 @@ const pixma_config_t pixma_iclass_devices[] = {
|
|||
DEV ("Canon imageCLASS MF634C", "MF632C/634C", MF634_PID, 600, 0, 637, 1050, PIXMA_CAP_ADFDUP),
|
||||
DEV ("Canon imageCLASS MF733C", "MF731C/733C", MF731_PID, 600, 0, 637, 1050, PIXMA_CAP_ADFDUP), /* however, we need this for ethernet/wifi */
|
||||
DEV ("Canon imageCLASS D570", "D570", D570_PID, 600, 0, 640, 877, 0),
|
||||
DEV ("Canon i-SENSYS MF110 Series", "MF110", MF110_PID, 600, 0, 640, 1050, 0),
|
||||
DEV ("Canon i-SENSYS MF110/910 Series", "MF110", MF110_PID, 600, 0, 640, 1050, 0),
|
||||
DEV ("Canon i-SENSYS MF520 Series", "MF520", MF520_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP),
|
||||
DEV ("Canon i-SENSYS MF420 Series", "MF420", MF420_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP),
|
||||
DEV ("Canon i-SENSYS MF260 Series", "MF260", MF260_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP),
|
||||
DEV ("Canon i-SENSYS MF740 Series", "MF740", MF740_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP),
|
||||
DEV ("Canon i-SENSYS MF741C/743C", "MF741C/743C", MF743_PID, 600, 300, 640, 1050, PIXMA_CAP_ADFDUP), /* ADFDUP restricted to 300dpi */
|
||||
DEV ("Canon i-SENSYS MF640 Series", "MF642C/643C/644C", MF640_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP),
|
||||
DEV ("Canon i-SENSYS MF645C", "MF645C", MF645_PID, 600, 0, 637, 877, PIXMA_CAP_ADFDUP), /* max. w = 216mm */
|
||||
DEV (NULL, NULL, 0, 0, 0, 0, 0, 0)
|
|
@ -107,39 +107,6 @@ get_scanner_info (unsigned devnr)
|
|||
return si;
|
||||
}
|
||||
|
||||
static const struct pixma_config_t *lookup_scanner(const char *makemodel,
|
||||
const struct pixma_config_t *const pixma_devices[])
|
||||
{
|
||||
int i;
|
||||
const struct pixma_config_t *cfg;
|
||||
char *match;
|
||||
|
||||
for (i = 0; pixma_devices[i]; i++)
|
||||
{
|
||||
/* loop through the device classes (mp150, mp730 etc) */
|
||||
for (cfg = pixma_devices[i]; cfg->name; cfg++)
|
||||
{
|
||||
/* loop through devices in class */
|
||||
if ((match = strcasestr (makemodel, cfg->model)) != NULL)
|
||||
{
|
||||
/* possible match found, make sure it is not a partial match */
|
||||
/* MP600 and MP600R are different models! */
|
||||
/* some models contain ranges, so check for a '-' too */
|
||||
|
||||
if ((match[strlen(cfg->model)] == ' ') ||
|
||||
(match[strlen(cfg->model)] == '\0') ||
|
||||
(match[strlen(cfg->model)] == '-'))
|
||||
{
|
||||
pixma_dbg (3, "Scanner model found: Name %s(%s) matches %s\n", cfg->model, cfg->name, makemodel);
|
||||
return cfg;
|
||||
}
|
||||
}
|
||||
pixma_dbg (20, "Scanner model %s(%s) not found, giving up! %s\n", cfg->model, cfg->name, makemodel);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static SANE_Status
|
||||
attach (SANE_String_Const devname)
|
||||
{
|
||||
|
@ -160,13 +127,11 @@ attach (SANE_String_Const devname)
|
|||
|
||||
|
||||
static SANE_Status
|
||||
attach_bjnp (SANE_String_Const devname, SANE_String_Const makemodel,
|
||||
attach_bjnp (SANE_String_Const devname,
|
||||
SANE_String_Const serial,
|
||||
const struct pixma_config_t *const pixma_devices[])
|
||||
const struct pixma_config_t *cfg)
|
||||
{
|
||||
scanner_info_t *si;
|
||||
const pixma_config_t *cfg;
|
||||
SANE_Status error;
|
||||
|
||||
si = (scanner_info_t *) calloc (1, sizeof (*si));
|
||||
if (!si)
|
||||
|
@ -174,19 +139,14 @@ attach_bjnp (SANE_String_Const devname, SANE_String_Const makemodel,
|
|||
si->devname = strdup (devname);
|
||||
if (!si->devname)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
if ((cfg = lookup_scanner(makemodel, pixma_devices)) == (struct pixma_config_t *)NULL)
|
||||
error = SANE_STATUS_INVAL;
|
||||
else
|
||||
{
|
||||
si->cfg = cfg;
|
||||
sprintf(si->serial, "%s_%s", cfg->model, serial);
|
||||
si -> interface = INT_BJNP;
|
||||
si->next = first_scanner;
|
||||
first_scanner = si;
|
||||
nscanners++;
|
||||
error = SANE_STATUS_GOOD;
|
||||
}
|
||||
return error;
|
||||
|
||||
si->cfg = cfg;
|
||||
sprintf(si->serial, "%s_%s", cfg->model, serial);
|
||||
si -> interface = INT_BJNP;
|
||||
si->next = first_scanner;
|
||||
first_scanner = si;
|
||||
nscanners++;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
static void
|
|
@ -1765,7 +1765,7 @@ const pixma_config_t pixma_mp150_devices[] = {
|
|||
|
||||
/* Latest devices (2018) Generation 5 CIS */
|
||||
DEVICE ("Canon MAXIFY MB5400 Series", "MB5400", MB5400_PID, 0, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP | PIXMA_CAP_ADF_JPEG),
|
||||
DEVICE ("Canon MAXIFY MB5100 Series", "MB5100", MB5100_PID, 0, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP),
|
||||
DEVICE ("Canon MAXIFY MB5100 Series", "MB5100", MB5100_PID, 0, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP | PIXMA_CAP_ADF_JPEG),
|
||||
DEVICE ("Canon PIXMA TS9100 Series", "TS9100", TS9100_PID, 0, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS),
|
||||
DEVICE ("Canon PIXMA TR8500 Series", "TR8500", TR8500_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF),
|
||||
DEVICE ("Canon PIXMA TR7500 Series", "TR7500", TR7500_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF),
|
|
@ -306,7 +306,7 @@ cano_AdjustLightsource( Plustek_Device *dev )
|
|||
min_rgb.Blue = hw->blue_lamp_on;
|
||||
|
||||
if((dev->adj.rlampoff != -1) &&
|
||||
(dev->adj.glampoff != -1) && (dev->adj.rlampoff != -1)) {
|
||||
(dev->adj.glampoff != -1) && (dev->adj.blampoff != -1)) {
|
||||
DBG( _DBG_INFO, "- function skipped, using frontend values!\n" );
|
||||
return SANE_TRUE;
|
||||
}
|
||||
|
|
|
@ -212,6 +212,7 @@ static int isSupportedDevice(struct device __sane_unused__ *dev)
|
|||
/* blacklist malfunctioning device(s) */
|
||||
if (!strncmp(dev->sane.model, "SCX-4500W", 9) ||
|
||||
!strncmp(dev->sane.model, "C460", 4) ||
|
||||
!!strstr(dev->sane.model, "CLX-3170") ||
|
||||
!strncmp(dev->sane.model, "M288x", 5))
|
||||
return 0;
|
||||
return 1;
|
||||
|
|
48
configure.ac
48
configure.ac
|
@ -769,54 +769,6 @@ AC_ARG_ENABLE(parport-directio,
|
|||
fi
|
||||
])
|
||||
|
||||
dnl ******************************************************************
|
||||
dnl SANE API specification format conversion support
|
||||
dnl ******************************************************************
|
||||
AC_ARG_WITH(api-spec,
|
||||
AS_HELP_STRING([--with-api-spec],
|
||||
[convert API spec to supported output formats @<:@default=check@:>@]),
|
||||
[],
|
||||
[with_api_spec=check])
|
||||
dnl Test for all tools that may be involved. These tests are fast and
|
||||
dnl running them allows for the Makefile targets to be formulated such
|
||||
dnl that any non-requested formats can be made using a one-off without
|
||||
dnl the need to reconfigure.
|
||||
AC_PATH_PROG(MAKEINDEX, makeindex, no)
|
||||
AC_PATH_PROG(DVIPS, dvips, no)
|
||||
AC_PATH_PROG(LATEX, latex, no)
|
||||
AC_PATH_PROG(PDFLATEX, pdflatex, no)
|
||||
AC_PATH_PROG(FIG2DEV, fig2dev, no)
|
||||
AC_PATH_PROG(GS, gs, no)
|
||||
AC_PATH_PROG(DLH, dlh, no)
|
||||
AC_PATH_PROG(PPMTOGIF, ppmtogif, no)
|
||||
AS_IF([test xno != "x$with_api_spec"],
|
||||
[dnl Flag formats for which all required tools have been found
|
||||
AS_IF([ test xno != "x$MAKEINDEX" \
|
||||
&& test xno != "x$DVIPS" \
|
||||
&& test xno != "x$FIG2DEV" \
|
||||
&& test xno != "x$LATEX"], [with_api_ps=yes])
|
||||
AS_IF([ test xno != "x$MAKEINDEX" \
|
||||
&& test xno != "x$PDFLATEX" \
|
||||
&& test xno != "x$FIG2DEV" \
|
||||
&& test xno != "x$GS"], [with_api_pdf=yes])
|
||||
AS_IF([ test xno != "x$MAKEINDEX" \
|
||||
&& test xno != "x$DVIPS" \
|
||||
&& test xno != "x$FIG2DEV" \
|
||||
&& test xno != "x$DLH" \
|
||||
&& test xno != "x$GS" \
|
||||
&& test xno != "x$PPMTOFIG" ], [with_api_html=yes])
|
||||
|
||||
AS_IF([test xyes = "x$with_api_spec" \
|
||||
&& test xyes != "x$with_api_ps" \
|
||||
&& test xyes != "x$with_api_pdf" \
|
||||
&& test xyes != "x$with_api_html"],
|
||||
[AC_MSG_ERROR([tools to convert the API spec are missing])
|
||||
])
|
||||
])
|
||||
AM_CONDITIONAL(WITH_API_PS, [test x$with_api_ps = xyes])
|
||||
AM_CONDITIONAL(WITH_API_PDF, [test x$with_api_pdf = xyes])
|
||||
AM_CONDITIONAL(WITH_API_HTML, [test x$with_api_html = xyes])
|
||||
|
||||
dnl ***********************************************************************
|
||||
dnl Write output files
|
||||
dnl ***********************************************************************
|
||||
|
|
|
@ -2,24 +2,11 @@
|
|||
*.5
|
||||
*.7
|
||||
*.8
|
||||
*.eps
|
||||
*.html
|
||||
*.pdf
|
||||
descriptions-external.db
|
||||
descriptions.db
|
||||
doxygen-genesys.conf
|
||||
doxygen-sanei.conf
|
||||
doxygen_sqlite3.db
|
||||
genesys-html
|
||||
sane.aux
|
||||
sane.cb
|
||||
sane.dvi
|
||||
sane.idx
|
||||
sane.ilg
|
||||
sane.ind
|
||||
sane.lof
|
||||
sane.log
|
||||
sane.lot
|
||||
sane.ps
|
||||
sane.toc
|
||||
sanei-html
|
||||
|
|
|
@ -82,11 +82,10 @@ HTML_PAGES = sane-backends.html sane-backends-external.html \
|
|||
endif
|
||||
doc_DATA = $(HTML_PAGES)
|
||||
|
||||
all: bemans $(API_SPECS) html-pages
|
||||
all: bemans html-pages
|
||||
|
||||
dist_doc_DATA = backend-writing.txt
|
||||
nobase_dist_doc_DATA = $(BEDOCS)
|
||||
doc_DATA += $(API_SPECS)
|
||||
EXTRA_DIST += descriptions.txt releases.txt sane-logo2.jpg sane-logo.png \
|
||||
sane.png
|
||||
|
||||
|
@ -218,89 +217,6 @@ install-data-local: install-beman5
|
|||
uninstall-local:
|
||||
rm -rf $(DESTDIR)$(beman5dir)/sane-*.5
|
||||
|
||||
## SANE API specification format conversion support
|
||||
|
||||
API_SPECS =
|
||||
if WITH_API_PS
|
||||
API_SPECS += sane.ps
|
||||
endif
|
||||
if WITH_API_PDF
|
||||
API_SPECS += sane.pdf
|
||||
endif
|
||||
if WITH_API_HTML
|
||||
API_SPECS += sane-html
|
||||
endif
|
||||
|
||||
API_SPEC_INPUTS = $(srcdir)/sane.tex
|
||||
API_SPEC_INPUTS += $(srcdir)/net.tex
|
||||
EXTRA_DIST += $(API_SPEC_INPUTS)
|
||||
|
||||
API_SPEC_TEX_FIGS =
|
||||
API_SPEC_TEX_FIGS += figs/area.fig
|
||||
API_SPEC_TEX_FIGS += figs/flow.fig
|
||||
API_SPEC_TEX_FIGS += figs/hierarchy.fig
|
||||
API_SPEC_TEX_FIGS += figs/image-data.fig
|
||||
API_SPEC_TEX_FIGS += figs/xfer.fig
|
||||
EXTRA_DIST += $(API_SPEC_TEX_FIGS)
|
||||
|
||||
API_SPEC_EPS_FIGS =
|
||||
API_SPEC_EPS_FIGS += figs/area.eps
|
||||
API_SPEC_EPS_FIGS += figs/flow.eps
|
||||
API_SPEC_EPS_FIGS += figs/hierarchy.eps
|
||||
API_SPEC_EPS_FIGS += figs/image-data.eps
|
||||
API_SPEC_EPS_FIGS += figs/xfer.eps
|
||||
|
||||
API_SPEC_PDF_FIGS =
|
||||
API_SPEC_PDF_FIGS += figs/area.pdf
|
||||
API_SPEC_PDF_FIGS += figs/flow.pdf
|
||||
API_SPEC_PDF_FIGS += figs/hierarchy.pdf
|
||||
API_SPEC_PDF_FIGS += figs/image-data.pdf
|
||||
API_SPEC_PDF_FIGS += figs/xfer.pdf
|
||||
|
||||
## These icons are referred to in the generated HTML output.
|
||||
API_SPEC_HTML_ICONS =
|
||||
API_SPEC_HTML_ICONS += icons/contents.gif
|
||||
API_SPEC_HTML_ICONS += icons/index.gif
|
||||
API_SPEC_HTML_ICONS += icons/next.gif icons/next_gr.gif
|
||||
API_SPEC_HTML_ICONS += icons/previous.gif icons/previous_gr.gif
|
||||
API_SPEC_HTML_ICONS += icons/references.gif icons/references_gr.gif
|
||||
API_SPEC_HTML_ICONS += icons/up.gif icons/up_gr.gif
|
||||
EXTRA_DIST += $(API_SPEC_HTML_ICONS)
|
||||
|
||||
am_TEXINPUTS = TEXINPUTS="$(builddir):$(srcdir):$$TEXINPUTS"
|
||||
|
||||
sane.ind: $(API_SPEC_INPUTS)
|
||||
@echo Generating index for $<...
|
||||
@touch sane.ind
|
||||
@$(am_TEXINPUTS) $(LATEX) $< </dev/null >/dev/null && \
|
||||
$(MAKEINDEX) -q sane.idx && \
|
||||
$(am_TEXINPUTS) $(LATEX) $< </dev/null >/dev/null
|
||||
|
||||
.fig.eps:
|
||||
@test -d $(@D) || $(MKDIR_P) $(@D)
|
||||
$(FIG2DEV) -L eps $< $@
|
||||
|
||||
sane.dvi: $(API_SPEC_INPUTS) $(API_SPEC_EPS_FIGS) sane.ind
|
||||
@echo Generating $@ from $<...
|
||||
@$(am_TEXINPUTS) $(LATEX) $< </dev/null >/dev/null
|
||||
|
||||
sane.ps: sane.dvi
|
||||
@echo Generating $@ from $<...
|
||||
@$(am_TEXINPUTS) $(DVIPS) -q $< -o $@
|
||||
|
||||
.fig.pdf:
|
||||
@test -d $(@D) || $(MKDIR_P) $(@D)
|
||||
$(FIG2DEV) -L pdf $< $@
|
||||
|
||||
sane.pdf: $(API_SPEC_INPUTS) $(API_SPEC_PDF_FIGS) sane.ind
|
||||
@echo Generating $@ from $<...
|
||||
@$(am_TEXINPUTS) $(PDFLATEX) $< >/dev/null
|
||||
|
||||
sane-html: sane.dvi
|
||||
$(am_TEXINPUTS) $(DLH) $(srcdir)/sane.tex
|
||||
|
||||
## ^^
|
||||
|
||||
html-man: $(MANPAGES)
|
||||
@for page in $(MANPAGES); do \
|
||||
echo "translating $${page} to $${page}.html..."; \
|
||||
|
@ -347,20 +263,12 @@ descriptions-external.db: $(DESC_EXT_FILES) ../tools/sane-desc
|
|||
> descriptions-external.db
|
||||
|
||||
html-pages: $(HTML_PAGES)
|
||||
html-local: html-pages html-man sane-html
|
||||
|
||||
clean-local:
|
||||
rm -f *.toc *.aux *.log *.cp *.fn *.tp *.vr *.pg *.ky *.blg *.idx *.cb
|
||||
rm -f *.ilg
|
||||
rm -f $(API_SPEC_EPS_FIGS) $(API_SPEC_PDF_FIGS)
|
||||
-rmdir figs
|
||||
html-local: html-pages html-man
|
||||
|
||||
distclean-local:
|
||||
rm -f $(MANPAGES)
|
||||
rm -f *.lot *.lof *.ind
|
||||
rm -f sane.dvi sane.ps sane-backends.html sane-backends-external.html
|
||||
rm -f sane-backends.html sane-backends-external.html
|
||||
rm -f sane-mfgs.html sane-mfgs-external.html
|
||||
rm -f sane/*.html sane/*.gif
|
||||
rm -f doxygen-sanei.conf doxygen-genesys.conf
|
||||
-rm -rf sane sanei-html
|
||||
for manpage in $(MANPAGES) ; do \
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Ładowanie…
Reference in New Issue