2019-06-02 08:47:26 +00:00
 /* sane - Scanner Access Now Easy.
2005-06-27 20:07:45 +00:00
Copyright ( C ) 2003 Oliver Rauch
Copyright ( C ) 2003 , 2004 Henning Meier - Geinitz < henning @ meier - geinitz . de >
Copyright ( C ) 2004 , 2005 Gerhard Jaeger < gerhard @ gjaeger . de >
2016-02-12 07:11:20 +00:00
Copyright ( C ) 2004 - 2013 St é phane Voltz < stef . dev @ free . fr >
2009-02-27 12:37:16 +00:00
Copyright ( C ) 2005 - 2009 Pierre Willenbrock < pierre @ pirsoft . dnsalias . org >
2006-03-27 14:41:30 +00:00
Copyright ( C ) 2006 Laurent Charpentier < laurent_pubs @ yahoo . com >
2005-06-27 20:07:45 +00:00
Parts of the structs have been taken from the gt68xx backend by
Sergey Vlasov < vsu @ altlinux . ru > et al .
2013-12-16 04:45:31 +00:00
2005-06-27 20:07:45 +00:00
This file is part of the SANE package .
2013-12-16 04:45:31 +00:00
2005-06-27 20:07:45 +00:00
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 .
2013-12-16 04:45:31 +00:00
2005-06-27 20:07:45 +00:00
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 .
2013-12-16 04:45:31 +00:00
2005-06-27 20:07:45 +00:00
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 .
2013-12-16 04:45:31 +00:00
2005-06-27 20:07:45 +00:00
As a special exception , the authors of SANE give permission for
additional uses of the libraries contained in this release of SANE .
2013-12-16 04:45:31 +00:00
2005-06-27 20:07:45 +00:00
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 .
2013-12-16 04:45:31 +00:00
2005-06-27 20:07:45 +00:00
This exception does not , however , invalidate any other reasons why
the executable file might be covered by the GNU General Public
License .
2013-12-16 04:45:31 +00:00
2005-06-27 20:07:45 +00:00
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 .
2013-12-16 04:45:31 +00:00
2005-06-27 20:07:45 +00:00
If you write modifications of your own for SANE , it is your choice
whether to permit this exception to apply to your modifications .
2013-12-16 04:45:31 +00:00
If you do not wish that , delete this exception notice .
2005-06-27 20:07:45 +00:00
*/
# ifndef GENESYS_LOW_H
# define GENESYS_LOW_H
2011-11-02 07:33:45 +00:00
# include "../include/sane/config.h"
# include <errno.h>
# include <string.h>
# include <stdlib.h>
# include <stdio.h>
# include <unistd.h>
# include <math.h>
2005-06-27 20:07:45 +00:00
# include <stddef.h>
2009-07-09 05:54:58 +00:00
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# endif
2011-11-01 15:10:07 +00:00
# ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
# endif
2013-12-16 04:45:31 +00:00
# ifdef HAVE_MKDIR
2011-11-03 21:47:10 +00:00
# include <sys/stat.h>
# include <sys/types.h>
# endif
2011-11-02 07:33:45 +00:00
2005-06-27 20:07:45 +00:00
# include "../include/sane/sane.h"
2011-11-02 07:33:45 +00:00
# include "../include/sane/sanei.h"
# include "../include/sane/saneopts.h"
# include "../include/sane/sanei_backend.h"
# include "../include/sane/sanei_usb.h"
# include "../include/_stdint.h"
2005-06-27 20:07:45 +00:00
2019-07-05 23:10:04 +00:00
# include "genesys_error.h"
2019-07-05 23:10:07 +00:00
# include "genesys_sanei.h"
2019-07-22 23:00:42 +00:00
# include "genesys_serialize.h"
2019-07-05 23:10:04 +00:00
2019-05-25 08:15:26 +00:00
# include <algorithm>
# include <array>
2019-05-25 08:15:28 +00:00
# include <cstring>
2019-05-25 08:15:26 +00:00
# include <functional>
2019-07-22 23:00:42 +00:00
# include <iostream>
2019-06-08 11:04:14 +00:00
# include <limits>
2019-05-25 07:03:14 +00:00
# include <memory>
# include <stdexcept>
2019-05-25 08:15:42 +00:00
# include <string>
2019-05-25 08:15:26 +00:00
# include <vector>
2019-05-25 07:03:14 +00:00
2013-01-28 21:04:37 +00:00
# define FREE_IFNOT_NULL(x) if(x!=NULL) { free(x); x=NULL;}
2012-12-09 14:41:06 +00:00
# define GENESYS_RED 0
# define GENESYS_GREEN 1
# define GENESYS_BLUE 2
2005-06-27 20:07:45 +00:00
/* Flags */
2012-10-24 19:28:42 +00:00
# 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_LAZY_INIT (1 << 2) /**< skip extensive ASIC test at init */
2010-02-16 06:24:56 +00:00
# define GENESYS_FLAG_XPA (1 << 3)
2012-10-24 19:28:42 +00:00
# define GENESYS_FLAG_SKIP_WARMUP (1 << 4) /**< skip genesys_warmup() */
2011-11-02 07:33:45 +00:00
/** @brief offset calibration flag
* signals that the scanner does offset calibration . In this case off_calibration ( ) and
2013-12-16 04:45:31 +00:00
* coarse_gain_calibration ( ) functions must be implemented
2011-11-02 07:33:45 +00:00
*/
# define GENESYS_FLAG_OFFSET_CALIBRATION (1 << 5)
2012-10-24 19:28:42 +00:00
# define GENESYS_FLAG_SEARCH_START (1 << 6) /**< do start search before scanning */
2013-12-16 04:45:31 +00:00
# define GENESYS_FLAG_REPARK (1 << 7) / **< repark head (and check for lock) by
2005-06-27 20:07:45 +00:00
moving without scanning */
2012-10-24 19:28:42 +00:00
# define GENESYS_FLAG_DARK_CALIBRATION (1 << 8) /**< do dark calibration */
# define GENESYS_FLAG_STAGGERED_LINE (1 << 9) /**< pixel columns are shifted vertically for hi-res modes */
2005-06-27 20:07:45 +00:00
2012-10-24 19:28:42 +00:00
# define GENESYS_FLAG_MUST_WAIT (1 << 10) /**< tells wether the scanner must wait for the head when parking */
2005-11-19 22:51:01 +00:00
2012-10-24 19:28:42 +00:00
# define GENESYS_FLAG_HAS_UTA (1 << 11) /**< scanner has a transparency adapter */
2005-11-19 22:51:01 +00:00
2012-10-24 19:28:42 +00:00
# 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 */
2019-06-08 11:03:55 +00:00
// scanner has infrared transparency scanning capability
# define GENESYS_FLAG_HAS_UTA_INFRARED (1 << 20)
2009-01-19 05:46:43 +00:00
2012-10-24 19:28:42 +00:00
# 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 */
# define GENESYS_HAS_COPY_SW (1 << 2) /**< scanner has COPY button */
# define GENESYS_HAS_EMAIL_SW (1 << 3) /**< scanner has EMAIL button */
# define GENESYS_HAS_PAGE_LOADED_SW (1 << 4) /**< scanner has paper in detection */
# define GENESYS_HAS_OCR_SW (1 << 5) /**< scanner has OCR button */
# define GENESYS_HAS_POWER_SW (1 << 6) /**< scanner has power button */
# define GENESYS_HAS_CALIBRATE (1 << 7) /**< scanner has 'calibrate' software button to start calibration */
2013-01-31 05:12:09 +00:00
# define GENESYS_HAS_EXTRA_SW (1 << 8) /**< scanner has extra function button */
2009-01-18 14:20:55 +00:00
2005-06-27 20:07:45 +00:00
/* USB control message values */
# define REQUEST_TYPE_IN (USB_TYPE_VENDOR | USB_DIR_IN)
# define REQUEST_TYPE_OUT (USB_TYPE_VENDOR | USB_DIR_OUT)
# define REQUEST_REGISTER 0x0c
# define REQUEST_BUFFER 0x04
# define VALUE_BUFFER 0x82
# define VALUE_SET_REGISTER 0x83
# define VALUE_READ_REGISTER 0x84
# define VALUE_WRITE_REGISTER 0x85
# define VALUE_INIT 0x87
# define GPIO_OUTPUT_ENABLE 0x89
# define GPIO_READ 0x8a
# define GPIO_WRITE 0x8b
2010-04-25 19:32:44 +00:00
# define VALUE_BUF_ENDACCESS 0x8c
# define VALUE_GET_REGISTER 0x8e
2005-06-27 20:07:45 +00:00
# define INDEX 0x00
/* todo: used?
# define VALUE_READ_STATUS 0x86
*/
/* Read/write bulk data/registers */
# define BULK_OUT 0x01
# define BULK_IN 0x00
# define BULK_RAM 0x00
# define BULK_REGISTER 0x11
# define BULKOUT_MAXSIZE 0xF000
/* AFE values */
# define AFE_INIT 1
# define AFE_SET 2
# define AFE_POWER_SAVE 4
2010-04-25 19:32:44 +00:00
# define LOWORD(x) ((uint16_t)((x) & 0xffff))
# define HIWORD(x) ((uint16_t)((x) >> 16))
2009-02-26 03:15:43 +00:00
# define LOBYTE(x) ((uint8_t)((x) & 0xFF))
# define HIBYTE(x) ((uint8_t)((x) >> 8))
2005-06-27 20:07:45 +00:00
/* Global constants */
2010-11-06 20:12:56 +00:00
/* TODO: emove this leftover of early backend days */
2005-06-27 20:07:45 +00:00
# define MOTOR_SPEED_MAX 350
# define DARK_VALUE 0
2010-11-06 20:12:56 +00:00
# define PWRBIT 0x80
# define BUFEMPTY 0x40
# define FEEDFSH 0x20
# define SCANFSH 0x10
# define HOMESNR 0x08
# define LAMPSTS 0x04
# define FEBUSY 0x02
# define MOTORENB 0x01
2005-06-27 20:07:45 +00:00
2019-06-02 08:47:26 +00:00
# define GENESYS_MAX_REGS 256
2019-06-08 11:04:15 +00:00
enum class ScanMethod : unsigned {
2019-06-08 11:03:54 +00:00
// normal scan method
FLATBED = 0 ,
// scan using transparency adaptor
2019-06-08 11:03:55 +00:00
TRANSPARENCY = 1 ,
// scan using transparency adaptor via infrared channel
TRANSPARENCY_INFRARED = 2
2019-06-08 11:03:54 +00:00
} ;
2019-07-22 23:00:42 +00:00
inline void serialize ( std : : istream & str , ScanMethod & x )
{
unsigned value ;
serialize ( str , value ) ;
x = static_cast < ScanMethod > ( value ) ;
}
inline void serialize ( std : : ostream & str , ScanMethod & x )
{
unsigned value = static_cast < unsigned > ( x ) ;
serialize ( str , value ) ;
}
2019-06-08 11:04:15 +00:00
enum class ScanColorMode : unsigned {
2019-06-08 11:03:57 +00:00
LINEART = 0 ,
HALFTONE ,
GRAY ,
COLOR_SINGLE_PASS
} ;
2019-07-22 23:00:42 +00:00
inline void serialize ( std : : istream & str , ScanColorMode & x )
{
unsigned value ;
serialize ( str , value ) ;
x = static_cast < ScanColorMode > ( value ) ;
}
inline void serialize ( std : : ostream & str , ScanColorMode & x )
{
unsigned value = static_cast < unsigned > ( x ) ;
serialize ( str , value ) ;
}
2019-06-08 11:04:16 +00:00
enum class ColorFilter : unsigned {
RED = 0 ,
GREEN ,
BLUE ,
NONE
} ;
2019-07-22 23:00:42 +00:00
inline void serialize ( std : : istream & str , ColorFilter & x )
{
unsigned value ;
serialize ( str , value ) ;
x = static_cast < ColorFilter > ( value ) ;
}
inline void serialize ( std : : ostream & str , ColorFilter & x )
{
unsigned value = static_cast < unsigned > ( x ) ;
serialize ( str , value ) ;
}
2019-06-02 08:47:26 +00:00
struct GenesysRegister {
uint16_t address = 0 ;
uint8_t value = 0 ;
} ;
inline bool operator < ( const GenesysRegister & lhs , const GenesysRegister & rhs )
2005-06-27 20:07:45 +00:00
{
2019-06-02 08:47:26 +00:00
return lhs . address < rhs . address ;
}
2019-06-08 11:04:28 +00:00
struct GenesysRegisterSetState {
bool is_lamp_on = false ;
bool is_xpa_on = false ;
} ;
2019-06-02 08:47:26 +00:00
class Genesys_Register_Set {
public :
using container = std : : vector < GenesysRegister > ;
using iterator = typename container : : iterator ;
using const_iterator = typename container : : const_iterator ;
2019-06-08 11:04:28 +00:00
// FIXME: this shouldn't live here, but in a separate struct that contains Genesys_Register_Set
GenesysRegisterSetState state ;
2019-06-02 08:47:26 +00:00
enum Options {
SEQUENTIAL = 1
} ;
Genesys_Register_Set ( )
{
registers_ . reserve ( GENESYS_MAX_REGS ) ;
}
// by default the register set is sorted by address. In certain cases it's importand to send
// the registers in certain order: use the SEQUENTIAL option for that
Genesys_Register_Set ( Options opts ) : Genesys_Register_Set ( )
{
if ( ( opts & SEQUENTIAL ) = = SEQUENTIAL ) {
sorted_ = false ;
}
}
void init_reg ( uint16_t address , uint8_t default_value )
{
if ( find_reg_index ( address ) > = 0 ) {
set8 ( address , default_value ) ;
return ;
}
GenesysRegister reg ;
reg . address = address ;
reg . value = default_value ;
registers_ . push_back ( reg ) ;
if ( sorted_ )
std : : sort ( registers_ . begin ( ) , registers_ . end ( ) ) ;
}
void remove_reg ( uint16_t address )
{
int i = find_reg_index ( address ) ;
if ( i < 0 ) {
throw std : : runtime_error ( " the register does not exist " ) ;
}
registers_ . erase ( registers_ . begin ( ) + i ) ;
}
GenesysRegister & find_reg ( uint16_t address )
{
int i = find_reg_index ( address ) ;
if ( i < 0 ) {
throw std : : runtime_error ( " the register does not exist " ) ;
}
return registers_ [ i ] ;
}
const GenesysRegister & find_reg ( uint16_t address ) const
{
int i = find_reg_index ( address ) ;
if ( i < 0 ) {
throw std : : runtime_error ( " the register does not exist " ) ;
}
return registers_ [ i ] ;
}
GenesysRegister * find_reg_address ( uint16_t address )
{
return & find_reg ( address ) ;
}
const GenesysRegister * find_reg_address ( uint16_t address ) const
{
return & find_reg ( address ) ;
}
void set8 ( uint16_t address , uint8_t value )
{
find_reg ( address ) . value = value ;
}
void set8_mask ( uint16_t address , uint8_t value , uint8_t mask )
{
auto & reg = find_reg ( address ) ;
reg . value = ( reg . value & ~ mask ) | value ;
}
void set16 ( uint16_t address , uint16_t value )
{
find_reg ( address ) . value = ( value > > 8 ) & 0xff ;
find_reg ( address + 1 ) . value = value & 0xff ;
}
void set24 ( uint16_t address , uint32_t value )
{
find_reg ( address ) . value = ( value > > 16 ) & 0xff ;
find_reg ( address + 1 ) . value = ( value > > 8 ) & 0xff ;
find_reg ( address + 2 ) . value = value & 0xff ;
}
uint8_t get8 ( uint16_t address ) const
{
return find_reg ( address ) . value ;
}
uint16_t get16 ( uint16_t address ) const
{
return ( find_reg ( address ) . value < < 8 ) | find_reg ( address + 1 ) . value ;
}
uint32_t get24 ( uint16_t address ) const
{
return ( find_reg ( address ) . value < < 16 ) |
( find_reg ( address + 1 ) . value < < 8 ) |
find_reg ( address + 2 ) . value ;
}
void clear ( ) { registers_ . clear ( ) ; }
size_t size ( ) const { return registers_ . size ( ) ; }
iterator begin ( ) { return registers_ . begin ( ) ; }
const_iterator begin ( ) const { return registers_ . begin ( ) ; }
iterator end ( ) { return registers_ . end ( ) ; }
const_iterator end ( ) const { return registers_ . end ( ) ; }
private :
int find_reg_index ( uint16_t address ) const
{
if ( ! sorted_ ) {
for ( size_t i = 0 ; i < registers_ . size ( ) ; i + + ) {
if ( registers_ [ i ] . address = = address ) {
return i ;
}
}
return - 1 ;
}
GenesysRegister search ;
search . address = address ;
auto it = std : : lower_bound ( registers_ . begin ( ) , registers_ . end ( ) , search ) ;
if ( it = = registers_ . end ( ) )
return - 1 ;
if ( it - > address ! = address )
return - 1 ;
return std : : distance ( registers_ . begin ( ) , it ) ;
}
// registers are stored in a sorted vector
bool sorted_ = true ;
std : : vector < GenesysRegister > registers_ ;
} ;
2005-06-27 20:07:45 +00:00
2019-05-25 08:15:27 +00:00
template < class T , size_t Size >
struct AssignableArray : public std : : array < T , Size > {
AssignableArray ( ) = default ;
AssignableArray ( const AssignableArray & ) = default ;
AssignableArray & operator = ( const AssignableArray & ) = default ;
AssignableArray & operator = ( std : : initializer_list < T > init )
{
if ( init . size ( ) ! = std : : array < T , Size > : : size ( ) )
throw std : : runtime_error ( " An array of incorrect size assigned " ) ;
std : : copy ( init . begin ( ) , init . end ( ) , std : : array < T , Size > : : begin ( ) ) ;
return * this ;
}
} ;
2019-06-02 08:47:30 +00:00
struct GenesysRegisterSetting {
GenesysRegisterSetting ( ) = default ;
GenesysRegisterSetting ( uint16_t p_address , uint8_t p_value ) :
address ( p_address ) , value ( p_value )
{ }
GenesysRegisterSetting ( uint16_t p_address , uint8_t p_value , uint8_t p_mask ) :
address ( p_address ) , value ( p_value ) , mask ( p_mask )
{ }
uint16_t address = 0 ;
uint8_t value = 0 ;
uint8_t mask = 0xff ;
2019-07-22 23:00:44 +00:00
bool operator = = ( const GenesysRegisterSetting & other ) const
{
return address = = other . address & & value = = other . value & & mask = = other . mask ;
}
2019-06-02 08:47:30 +00:00
} ;
2019-07-22 23:00:42 +00:00
template < class Stream >
void serialize ( Stream & str , GenesysRegisterSetting & reg )
{
serialize ( str , reg . address ) ;
serialize ( str , reg . value ) ;
serialize ( str , reg . mask ) ;
}
2019-06-02 08:47:30 +00:00
class GenesysRegisterSettingSet {
public :
using container = std : : vector < GenesysRegisterSetting > ;
using iterator = typename container : : iterator ;
using const_iterator = typename container : : const_iterator ;
GenesysRegisterSettingSet ( ) = default ;
GenesysRegisterSettingSet ( std : : initializer_list < GenesysRegisterSetting > ilist ) : regs_ ( ilist ) { }
iterator begin ( ) { return regs_ . begin ( ) ; }
const_iterator begin ( ) const { return regs_ . begin ( ) ; }
iterator end ( ) { return regs_ . end ( ) ; }
const_iterator end ( ) const { return regs_ . end ( ) ; }
GenesysRegisterSetting & operator [ ] ( size_t i ) { return regs_ [ i ] ; }
const GenesysRegisterSetting & operator [ ] ( size_t i ) const { return regs_ [ i ] ; }
size_t size ( ) const { return regs_ . size ( ) ; }
bool empty ( ) const { return regs_ . empty ( ) ; }
void clear ( ) { regs_ . clear ( ) ; }
void push_back ( GenesysRegisterSetting reg ) { regs_ . push_back ( reg ) ; }
2019-06-02 08:47:52 +00:00
void merge ( const GenesysRegisterSettingSet & other )
{
for ( const auto & reg : other ) {
set_value ( reg . address , reg . value ) ;
}
}
2019-06-02 08:47:30 +00:00
uint8_t get_value ( uint16_t address ) const
{
for ( const auto & reg : regs_ ) {
if ( reg . address = = address )
return reg . value ;
}
throw std : : runtime_error ( " Unknown register " ) ;
}
void set_value ( uint16_t address , uint8_t value )
{
for ( auto & reg : regs_ ) {
if ( reg . address = = address ) {
reg . value = value ;
return ;
}
}
2019-06-02 08:47:52 +00:00
push_back ( GenesysRegisterSetting ( address , value ) ) ;
2019-06-02 08:47:30 +00:00
}
2019-07-22 23:00:42 +00:00
friend void serialize ( std : : istream & str , GenesysRegisterSettingSet & reg ) ;
friend void serialize ( std : : ostream & str , GenesysRegisterSettingSet & reg ) ;
2019-06-02 08:47:58 +00:00
2019-07-22 23:00:44 +00:00
bool operator = = ( const GenesysRegisterSettingSet & other ) const
{
return regs_ = = other . regs_ ;
}
2019-06-02 08:47:30 +00:00
private :
std : : vector < GenesysRegisterSetting > regs_ ;
} ;
2019-07-22 23:00:42 +00:00
inline void serialize ( std : : istream & str , GenesysRegisterSettingSet & reg )
{
reg . clear ( ) ;
const size_t max_register_address =
1 < < ( sizeof ( GenesysRegisterSetting : : address ) * CHAR_BIT ) ;
serialize ( str , reg . regs_ , max_register_address ) ;
}
inline void serialize ( std : : ostream & str , GenesysRegisterSettingSet & reg )
{
serialize ( str , reg . regs_ ) ;
}
2019-06-02 08:48:04 +00:00
struct GenesysFrontendLayout
{
std : : array < uint16_t , 3 > offset_addr = { } ;
std : : array < uint16_t , 3 > gain_addr = { } ;
2019-07-22 23:00:44 +00:00
bool operator = = ( const GenesysFrontendLayout & other ) const
{
return offset_addr = = other . offset_addr & & gain_addr = = other . gain_addr ;
}
2019-06-02 08:48:04 +00:00
} ;
/** @brief Data structure to set up analog frontend.
The analog frontend converts analog value from image sensor to digital value . It has its own
control registers which are set up with this structure . The values are written using
sanei_genesys_fe_write_data .
*/
struct Genesys_Frontend
{
Genesys_Frontend ( ) = default ;
// id of the frontend description
uint8_t fe_id = 0 ;
// all registers of the frontend
GenesysRegisterSettingSet regs ;
// extra control registers
std : : array < uint8_t , 3 > reg2 = { } ;
GenesysFrontendLayout layout ;
void set_offset ( unsigned which , uint8_t value )
{
regs . set_value ( layout . offset_addr [ which ] , value ) ;
}
void set_gain ( unsigned which , uint8_t value )
{
regs . set_value ( layout . gain_addr [ which ] , value ) ;
}
uint8_t get_offset ( unsigned which ) const
{
return regs . get_value ( layout . offset_addr [ which ] ) ;
}
uint8_t get_gain ( unsigned which ) const
{
return regs . get_value ( layout . gain_addr [ which ] ) ;
}
2019-07-22 23:00:44 +00:00
bool operator = = ( const Genesys_Frontend & other ) const
{
return fe_id = = other . fe_id & &
regs = = other . regs & &
reg2 = = other . reg2 & &
layout = = other . layout ;
}
2019-06-02 08:48:04 +00:00
} ;
2019-07-22 23:00:42 +00:00
template < class Stream >
void serialize ( Stream & str , Genesys_Frontend & x )
{
serialize ( str , x . fe_id ) ;
serialize_newline ( str ) ;
serialize ( str , x . regs ) ;
serialize_newline ( str ) ;
serialize ( str , x . reg2 ) ;
serialize_newline ( str ) ;
serialize ( str , x . layout . offset_addr ) ;
serialize ( str , x . layout . gain_addr ) ;
}
2019-06-02 08:48:04 +00:00
2019-06-02 08:47:31 +00:00
struct SensorExposure {
uint16_t red , green , blue ;
} ;
2019-05-25 08:15:27 +00:00
struct Genesys_Sensor {
2019-05-25 08:15:29 +00:00
Genesys_Sensor ( ) = default ;
~ Genesys_Sensor ( ) = default ;
2019-05-25 08:15:27 +00:00
// id of the sensor description
2019-05-25 08:15:29 +00:00
uint8_t sensor_id = 0 ;
2019-07-06 18:02:27 +00:00
// sensor resolution in CCD pixels. Note that we may read more than one CCD pixel per logical
// pixel, see ccd_pixels_per_system_pixel()
2019-05-25 08:15:29 +00:00
int optical_res = 0 ;
2019-06-02 08:47:52 +00:00
// the minimum and maximum resolution this sensor is usable at. -1 means that the resolution
// can be any.
int min_resolution = - 1 ;
int max_resolution = - 1 ;
2019-06-08 11:03:54 +00:00
// the scan method used with the sensor
ScanMethod method = ScanMethod : : FLATBED ;
2019-06-02 08:47:52 +00:00
2019-06-02 08:47:53 +00:00
// CCD may present itself as half or quarter-size CCD on certain resolutions
int ccd_size_divisor = 1 ;
2019-06-02 08:47:28 +00:00
2019-05-25 08:15:29 +00:00
int black_pixels = 0 ;
2019-05-25 08:15:27 +00:00
// value of the dummy register
2019-05-25 08:15:29 +00:00
int dummy_pixel = 0 ;
2019-05-25 08:15:27 +00:00
// last pixel of CCD margin at optical resolution
2019-05-25 08:15:29 +00:00
int CCD_start_xoffset = 0 ;
2019-05-25 08:15:27 +00:00
// total pixels used by the sensor
2019-05-25 08:15:29 +00:00
int sensor_pixels = 0 ;
2019-05-25 08:15:27 +00:00
// TA CCD target code (reference gain)
2019-05-25 08:15:29 +00:00
int fau_gain_white_ref = 0 ;
2019-05-25 08:15:27 +00:00
// CCD target code (reference gain)
2019-05-25 08:15:29 +00:00
int gain_white_ref = 0 ;
2019-05-25 08:15:27 +00:00
2019-06-02 08:47:31 +00:00
// red, green and blue initial exposure values
SensorExposure exposure ;
2019-06-02 08:47:52 +00:00
int exposure_lperiod = - 1 ;
2019-06-02 08:47:30 +00:00
GenesysRegisterSettingSet custom_regs ;
2019-06-02 08:48:01 +00:00
GenesysRegisterSettingSet custom_fe_regs ;
2019-05-25 08:15:27 +00:00
// red, green and blue gamma coefficient for default gamma tables
AssignableArray < float , 3 > gamma ;
2019-06-02 08:47:53 +00:00
int get_ccd_size_divisor_for_dpi ( int xres ) const
{
2019-06-02 08:47:54 +00:00
if ( ccd_size_divisor > = 4 & & xres * 4 < = optical_res ) {
return 4 ;
}
if ( ccd_size_divisor > = 2 & & xres * 2 < = optical_res ) {
return 2 ;
2019-06-02 08:47:53 +00:00
}
return 1 ;
}
2019-07-22 23:00:44 +00:00
2019-07-06 18:02:27 +00:00
// how many CCD pixels are processed per system pixel time. This corresponds to CKSEL + 1
unsigned ccd_pixels_per_system_pixel ( ) const
{
// same on GL646, GL841, GL843, GL846, GL847, GL124
constexpr unsigned REG_0x18_CKSEL = 0x03 ;
return ( custom_regs . get_value ( 0x18 ) & REG_0x18_CKSEL ) + 1 ;
}
2019-07-22 23:00:44 +00:00
bool operator = = ( const Genesys_Sensor & other ) const
{
return sensor_id = = other . sensor_id & &
optical_res = = other . optical_res & &
min_resolution = = other . min_resolution & &
max_resolution = = other . max_resolution & &
method = = other . method & &
ccd_size_divisor = = other . ccd_size_divisor & &
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 . blue = = other . exposure . blue & &
exposure . green = = other . exposure . green & &
exposure . red = = other . exposure . red & &
exposure_lperiod = = other . exposure_lperiod & &
custom_regs = = other . custom_regs & &
custom_fe_regs = = other . custom_fe_regs & &
gamma = = other . gamma ;
}
2019-05-25 08:15:27 +00:00
} ;
2005-06-27 20:07:45 +00:00
2019-07-22 23:00:42 +00:00
template < class Stream >
void serialize ( Stream & str , Genesys_Sensor & x )
{
serialize ( str , x . sensor_id ) ;
serialize ( str , x . optical_res ) ;
serialize ( str , x . min_resolution ) ;
serialize ( str , x . max_resolution ) ;
serialize ( str , x . method ) ;
serialize ( str , x . ccd_size_divisor ) ;
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 ) ;
serialize ( str , x . exposure . blue ) ;
serialize ( str , x . exposure . green ) ;
serialize ( str , x . exposure . red ) ;
serialize ( str , x . exposure_lperiod ) ;
serialize_newline ( str ) ;
serialize ( str , x . custom_regs ) ;
serialize_newline ( str ) ;
serialize ( str , x . custom_fe_regs ) ;
serialize_newline ( str ) ;
serialize ( str , x . gamma ) ;
}
2019-06-02 08:47:37 +00:00
struct Genesys_Gpo
2005-06-27 20:07:45 +00:00
{
2019-06-02 08:47:37 +00:00
Genesys_Gpo ( ) = default ;
Genesys_Gpo ( uint8_t id , const std : : array < uint8_t , 2 > & v , const std : : array < uint8_t , 2 > & e )
{
gpo_id = id ;
value [ 0 ] = v [ 0 ] ;
value [ 1 ] = v [ 1 ] ;
enable [ 0 ] = e [ 0 ] ;
enable [ 1 ] = e [ 1 ] ;
}
// Genesys_Gpo
uint8_t gpo_id = 0 ;
2019-05-18 11:55:56 +00:00
2019-06-02 08:47:37 +00:00
// registers 0x6c and 0x6d on GL841, GL842, GL843, GL846, GL848 and possibly others
uint8_t value [ 2 ] = { 0 , 0 } ;
2019-05-18 11:55:56 +00:00
2019-06-02 08:47:37 +00:00
// registers 0x6e and 0x6f on GL841, GL842, GL843, GL846, GL848 and possibly others
uint8_t enable [ 2 ] = { 0 , 0 } ;
} ;
2005-06-27 20:07:45 +00:00
2019-06-02 08:47:38 +00:00
struct Genesys_Motor_Slope
2005-06-27 20:07:45 +00:00
{
2019-06-02 08:47:38 +00:00
Genesys_Motor_Slope ( ) = default ;
Genesys_Motor_Slope ( int p_maximum_start_speed , int p_maximum_speed , int p_minimum_steps ,
float p_g ) :
maximum_start_speed ( p_maximum_start_speed ) ,
maximum_speed ( p_maximum_speed ) ,
minimum_steps ( p_minimum_steps ) ,
g ( p_g )
{ }
2005-11-19 22:51:01 +00:00
2019-06-02 08:47:38 +00:00
// maximum speed allowed when accelerating from standstill. Unit: pixeltime/step
int maximum_start_speed = 0 ;
// maximum speed allowed. Unit: pixeltime/step
int maximum_speed = 0 ;
// number of steps used for default curve
int minimum_steps = 0 ;
/* power for non-linear acceleration curves.
vs * ( 1 - i ^ g ) + ve * ( i ^ g ) where
vs = start speed , ve = end speed ,
i = 0.0 for first entry and i = 1.0 for last entry in default table
*/
float g = 0 ;
} ;
2005-11-19 22:51:01 +00:00
2019-06-02 08:47:38 +00:00
struct Genesys_Motor
2005-11-19 22:51:01 +00:00
{
2019-06-02 08:47:38 +00:00
Genesys_Motor ( ) = default ;
Genesys_Motor ( uint8_t p_motor_id , int p_base_ydpi , int p_optical_ydpi , int p_max_step_type ,
int p_power_mode_count ,
const std : : vector < std : : vector < Genesys_Motor_Slope > > & p_slopes ) :
motor_id ( p_motor_id ) ,
base_ydpi ( p_base_ydpi ) ,
optical_ydpi ( p_optical_ydpi ) ,
max_step_type ( p_max_step_type ) ,
power_mode_count ( p_power_mode_count ) ,
slopes ( p_slopes )
{ }
// id of the motor description
uint8_t motor_id = 0 ;
// motor base steps. Unit: 1/inch
int base_ydpi = 0 ;
// maximum resolution in y-direction. Unit: 1/inch
int optical_ydpi = 0 ;
// maximum step type. 0-2
int max_step_type = 0 ;
// number of power modes
int power_mode_count = 0 ;
// slopes to derive individual slopes from
std : : vector < std : : vector < Genesys_Motor_Slope > > slopes ;
} ;
2005-06-27 20:07:45 +00:00
typedef enum Genesys_Color_Order
{
COLOR_ORDER_RGB ,
COLOR_ORDER_BGR
}
Genesys_Color_Order ;
# define MAX_RESOLUTIONS 13
# define MAX_DPI 4
# define GENESYS_GL646 646
# define GENESYS_GL841 841
2010-07-20 20:04:11 +00:00
# define GENESYS_GL843 843
2013-06-26 04:51:55 +00:00
# define GENESYS_GL845 845
2010-04-25 19:32:44 +00:00
# define GENESYS_GL846 846
# define GENESYS_GL847 847
# define GENESYS_GL848 848
2013-01-28 21:04:37 +00:00
# define GENESYS_GL123 123
2010-11-06 20:12:56 +00:00
# define GENESYS_GL124 124
2005-06-27 20:07:45 +00:00
2019-04-22 21:55:44 +00:00
enum Genesys_Model_Type
{
MODEL_UMAX_ASTRA_4500 = 0 ,
MODEL_CANON_LIDE_50 ,
MODEL_PANASONIC_KV_SS080 ,
MODEL_HP_SCANJET_4850C ,
MODEL_HP_SCANJET_G4010 ,
MODEL_HP_SCANJET_G4050 ,
MODEL_CANON_CANOSCAN_4400F ,
MODEL_CANON_CANOSCAN_8400F ,
2019-05-18 11:56:02 +00:00
MODEL_CANON_CANOSCAN_8600F ,
2019-04-22 21:55:44 +00:00
MODEL_CANON_LIDE_100 ,
MODEL_CANON_LIDE_110 ,
MODEL_CANON_LIDE_120 ,
MODEL_CANON_LIDE_210 ,
MODEL_CANON_LIDE_220 ,
MODEL_CANON_CANOSCAN_5600F ,
MODEL_CANON_LIDE_700F ,
MODEL_CANON_LIDE_200 ,
MODEL_CANON_LIDE_60 ,
MODEL_CANON_LIDE_80 ,
MODEL_HP_SCANJET_2300C ,
MODEL_HP_SCANJET_2400C ,
MODEL_VISIONEER_STROBE_XP200 ,
MODEL_HP_SCANJET_3670C ,
MODEL_PLUSTEK_OPTICPRO_ST12 ,
MODEL_PLUSTEK_OPTICPRO_ST24 ,
MODEL_MEDION_MD5345 ,
MODEL_VISIONEER_STROBE_XP300 ,
MODEL_SYSCAN_DOCKETPORT_665 ,
MODEL_VISIONEER_ROADWARRIOR ,
MODEL_SYSCAN_DOCKETPORT_465 ,
MODEL_VISIONEER_STROBE_XP100_REVISION3 ,
MODEL_PENTAX_DSMOBILE_600 ,
MODEL_SYSCAN_DOCKETPORT_467 ,
MODEL_SYSCAN_DOCKETPORT_685 ,
MODEL_SYSCAN_DOCKETPORT_485 ,
MODEL_DCT_DOCKETPORT_487 ,
MODEL_VISIONEER_7100 ,
MODEL_XEROX_2400 ,
MODEL_XEROX_TRAVELSCANNER_100 ,
MODEL_PLUSTEK_OPTICPRO_3600 ,
MODEL_HP_SCANJET_N6310 ,
MODEL_PLUSTEK_OPTICBOOK_3800 ,
MODEL_CANON_IMAGE_FORMULA_101
} ;
2019-03-22 12:50:03 +00:00
enum Genesys_Dac_Type
{
DAC_WOLFSON_UMAX = 0 ,
DAC_WOLFSON_ST12 ,
DAC_WOLFSON_ST24 ,
DAC_WOLFSON_5345 ,
DAC_WOLFSON_HP2400 ,
DAC_WOLFSON_HP2300 ,
DAC_CANONLIDE35 ,
DAC_AD_XP200 ,
DAC_WOLFSON_XP300 ,
DAC_WOLFSON_HP3670 ,
DAC_WOLFSON_DSM600 ,
DAC_CANONLIDE200 ,
DAC_KVSS080 ,
DAC_G4050 ,
DAC_CANONLIDE110 ,
DAC_PLUSTEK_3600 ,
DAC_CANONLIDE700 ,
DAC_CS8400F ,
2019-05-18 11:56:02 +00:00
DAC_CS8600F ,
2019-03-22 12:50:03 +00:00
DAC_IMG101 ,
DAC_PLUSTEK3800 ,
DAC_CANONLIDE80 ,
DAC_CANONLIDE120
} ;
enum Genesys_Sensor_Type
{
CCD_UMAX = 0 ,
CCD_ST12 , // SONY ILX548: 5340 Pixel ???
CCD_ST24 , // SONY ILX569: 10680 Pixel ???
CCD_5345 ,
CCD_HP2400 ,
CCD_HP2300 ,
CCD_CANONLIDE35 ,
CIS_XP200 , // CIS sensor for Strobe XP200,
CCD_HP3670 ,
CCD_DP665 ,
CCD_ROADWARRIOR ,
CCD_DSMOBILE600 ,
CCD_XP300 ,
CCD_DP685 ,
CIS_CANONLIDE200 ,
CIS_CANONLIDE100 ,
CCD_KVSS080 ,
CCD_G4050 ,
CIS_CANONLIDE110 ,
CCD_PLUSTEK_3600 ,
CCD_HP_N6310 ,
CIS_CANONLIDE700 ,
CCD_CS4400F ,
CCD_CS8400F ,
2019-05-18 11:56:02 +00:00
CCD_CS8600F ,
2019-03-22 12:50:03 +00:00
CCD_IMG101 ,
CCD_PLUSTEK3800 ,
CIS_CANONLIDE210 ,
CIS_CANONLIDE80 ,
CIS_CANONLIDE220 ,
CIS_CANONLIDE120 ,
} ;
enum Genesys_Gpo_Type
{
GPO_UMAX ,
GPO_ST12 ,
GPO_ST24 ,
GPO_5345 ,
GPO_HP2400 ,
GPO_HP2300 ,
GPO_CANONLIDE35 ,
GPO_XP200 ,
GPO_XP300 ,
GPO_HP3670 ,
GPO_DP665 ,
GPO_DP685 ,
GPO_CANONLIDE200 ,
GPO_KVSS080 ,
GPO_G4050 ,
GPO_CANONLIDE110 ,
GPO_PLUSTEK_3600 ,
GPO_CANONLIDE210 ,
GPO_HP_N6310 ,
GPO_CANONLIDE700 ,
GPO_CS4400F ,
GPO_CS8400F ,
2019-05-18 11:56:02 +00:00
GPO_CS8600F ,
2019-03-22 12:50:03 +00:00
GPO_IMG101 ,
GPO_PLUSTEK3800 ,
GPO_CANONLIDE80 ,
GPO_CANONLIDE120
} ;
enum Genesys_Motor_Type
{
MOTOR_UMAX = 0 ,
MOTOR_5345 ,
MOTOR_ST24 ,
MOTOR_HP2400 ,
MOTOR_HP2300 ,
MOTOR_CANONLIDE35 ,
MOTOR_XP200 ,
MOTOR_XP300 ,
MOTOR_HP3670 ,
MOTOR_DP665 ,
MOTOR_ROADWARRIOR ,
MOTOR_DSMOBILE_600 ,
MOTOR_CANONLIDE200 ,
MOTOR_CANONLIDE100 ,
MOTOR_KVSS080 ,
MOTOR_G4050 ,
MOTOR_CANONLIDE110 ,
MOTOR_PLUSTEK_3600 ,
MOTOR_CANONLIDE700 ,
MOTOR_CS8400F ,
2019-05-18 11:56:02 +00:00
MOTOR_CS8600F ,
2019-03-22 12:50:03 +00:00
MOTOR_IMG101 ,
MOTOR_PLUSTEK3800 ,
MOTOR_CANONLIDE210 ,
MOTOR_CANONLIDE80 ,
MOTOR_CANONLIDE120
} ;
2005-06-27 20:07:45 +00:00
/* Forward typedefs */
typedef struct Genesys_Device Genesys_Device ;
2009-01-18 13:56:57 +00:00
struct Genesys_Scanner ;
2009-03-25 12:57:24 +00:00
typedef struct Genesys_Calibration_Cache Genesys_Calibration_Cache ;
2005-06-27 20:07:45 +00:00
/**
* Scanner command set description .
*
* This description contains parts which are common to all scanners with the
* same command set , but may have different optical resolution and other
* parameters .
*/
typedef struct Genesys_Command_Set
{
/** @name Identification */
/*@{ */
/** Name of this command set */
SANE_String_Const name ;
/*@} */
2019-06-30 11:05:28 +00:00
bool ( * needs_home_before_init_regs_for_scan ) ( Genesys_Device * dev ) ;
2005-06-27 20:07:45 +00:00
/** For ASIC initialization */
SANE_Status ( * init ) ( Genesys_Device * dev ) ;
SANE_Status ( * init_regs_for_warmup ) ( Genesys_Device * dev ,
2019-06-02 08:47:51 +00:00
const Genesys_Sensor & sensor ,
2005-06-27 20:07:45 +00:00
Genesys_Register_Set * regs ,
int * channels , int * total_size ) ;
2019-06-02 08:47:51 +00:00
SANE_Status ( * init_regs_for_coarse_calibration ) ( Genesys_Device * dev ,
2019-06-08 11:03:56 +00:00
const Genesys_Sensor & sensor ,
Genesys_Register_Set & regs ) ;
SANE_Status ( * init_regs_for_shading ) ( Genesys_Device * dev , const Genesys_Sensor & sensor ,
Genesys_Register_Set & regs ) ;
2019-06-02 08:47:51 +00:00
SANE_Status ( * init_regs_for_scan ) ( Genesys_Device * dev , const Genesys_Sensor & sensor ) ;
2005-06-27 20:07:45 +00:00
SANE_Bool ( * get_filter_bit ) ( Genesys_Register_Set * reg ) ;
SANE_Bool ( * get_lineart_bit ) ( Genesys_Register_Set * reg ) ;
SANE_Bool ( * get_bitset_bit ) ( Genesys_Register_Set * reg ) ;
SANE_Bool ( * get_gain4_bit ) ( Genesys_Register_Set * reg ) ;
SANE_Bool ( * get_fast_feed_bit ) ( Genesys_Register_Set * reg ) ;
SANE_Bool ( * test_buffer_empty_bit ) ( SANE_Byte val ) ;
SANE_Bool ( * test_motor_flag_bit ) ( SANE_Byte val ) ;
2019-06-02 08:47:51 +00:00
SANE_Status ( * set_fe ) ( Genesys_Device * dev , const Genesys_Sensor & sensor , uint8_t set ) ;
2005-06-27 20:07:45 +00:00
SANE_Status ( * set_powersaving ) ( Genesys_Device * dev , int delay ) ;
2005-11-19 22:51:01 +00:00
SANE_Status ( * save_power ) ( Genesys_Device * dev , SANE_Bool enable ) ;
2005-06-27 20:07:45 +00:00
SANE_Status ( * begin_scan ) ( Genesys_Device * dev ,
2019-06-02 08:47:51 +00:00
const Genesys_Sensor & sensor ,
2005-06-27 20:07:45 +00:00
Genesys_Register_Set * regs ,
SANE_Bool start_motor ) ;
SANE_Status ( * end_scan ) ( Genesys_Device * dev ,
Genesys_Register_Set * regs ,
SANE_Bool check_stop ) ;
2012-12-09 14:41:06 +00:00
/**
* Send gamma tables to ASIC
*/
2019-06-02 08:47:51 +00:00
SANE_Status ( * send_gamma_table ) ( Genesys_Device * dev , const Genesys_Sensor & sensor ) ;
2005-06-27 20:07:45 +00:00
SANE_Status ( * search_start_position ) ( Genesys_Device * dev ) ;
2019-06-08 11:03:56 +00:00
SANE_Status ( * offset_calibration ) ( Genesys_Device * dev , const Genesys_Sensor & sensor ,
Genesys_Register_Set & regs ) ;
2019-06-02 08:47:51 +00:00
SANE_Status ( * coarse_gain_calibration ) ( Genesys_Device * dev ,
2019-06-08 11:03:56 +00:00
const Genesys_Sensor & sensor ,
Genesys_Register_Set & regs , int dpi ) ;
SANE_Status ( * led_calibration ) ( Genesys_Device * dev , Genesys_Sensor & sensor ,
Genesys_Register_Set & regs ) ;
2005-06-27 20:07:45 +00:00
2019-06-30 11:05:27 +00:00
void ( * wait_for_motor_stop ) ( Genesys_Device * dev ) ;
2016-03-03 20:12:29 +00:00
SANE_Status ( * slow_back_home ) ( Genesys_Device * dev , SANE_Bool wait_until_home ) ;
SANE_Status ( * rewind ) ( Genesys_Device * dev ) ;
2009-01-16 15:31:10 +00:00
2005-11-19 22:51:01 +00:00
SANE_Status ( * bulk_write_register ) ( Genesys_Device * dev ,
2019-06-08 11:03:56 +00:00
Genesys_Register_Set & regs ) ;
2019-06-02 08:47:26 +00:00
2013-12-16 04:45:31 +00:00
SANE_Status ( * bulk_write_data ) ( Genesys_Device * dev , uint8_t addr ,
2009-02-26 03:15:43 +00:00
uint8_t * data , size_t len ) ;
2005-11-19 22:51:01 +00:00
2019-07-14 20:40:34 +00:00
void ( * bulk_read_data ) ( Genesys_Device * dev , uint8_t addr , uint8_t * data , size_t len ) ;
2005-06-27 20:07:45 +00:00
2019-06-08 11:03:47 +00:00
// Updates hardware sensor information in Genesys_Scanner.val[].
2009-01-19 05:46:43 +00:00
SANE_Status ( * update_hardware_sensors ) ( struct Genesys_Scanner * s ) ;
/* functions for sheetfed scanners */
/**
* load document into scanner
*/
SANE_Status ( * load_document ) ( Genesys_Device * dev ) ;
/**
* detects is the scanned document has left scanner . In this
* case it updates the amount of data to read and set up
* flags in the dev struct
*/
SANE_Status ( * detect_document_end ) ( Genesys_Device * dev ) ;
/**
* eject document from scanner
*/
SANE_Status ( * eject_document ) ( Genesys_Device * dev ) ;
2009-06-09 20:05:11 +00:00
/**
2013-12-16 04:45:31 +00:00
* search for an black or white area in forward or reverse
2009-06-09 20:05:11 +00:00
* direction */
2019-06-02 08:47:51 +00:00
SANE_Status ( * search_strip ) ( Genesys_Device * dev , const Genesys_Sensor & sensor ,
SANE_Bool forward , SANE_Bool black ) ;
2009-03-25 12:57:24 +00:00
2019-06-30 11:05:16 +00:00
bool ( * is_compatible_calibration ) ( Genesys_Device * dev , const Genesys_Sensor & sensor ,
Genesys_Calibration_Cache * cache , SANE_Bool for_overwrite ) ;
2010-03-15 05:24:23 +00:00
/* functions for transparency adapter */
/**
* move scanning head to transparency adapter
*/
SANE_Status ( * move_to_ta ) ( Genesys_Device * dev ) ;
2010-04-25 19:32:44 +00:00
/**
* write shading data calibration to ASIC
*/
2019-06-02 08:47:51 +00:00
SANE_Status ( * send_shading_data ) ( Genesys_Device * dev , const Genesys_Sensor & sensor ,
uint8_t * data , int size ) ;
2010-04-25 19:32:44 +00:00
2019-06-30 11:05:15 +00:00
// calculate current scan setup
void ( * calculate_current_setup ) ( Genesys_Device * dev , const Genesys_Sensor & sensor ) ;
2011-07-31 20:09:46 +00:00
2013-01-28 21:04:37 +00:00
/**
* cold boot init function
*/
SANE_Status ( * asic_boot ) ( Genesys_Device * dev , SANE_Bool cold ) ;
2005-06-27 20:07:45 +00:00
} Genesys_Command_Set ;
2011-08-25 04:43:25 +00:00
/** @brief structure to describe a scanner model
* This structure describes a model . It is composed of information on the
* sensor , the motor , scanner geometry and flags to drive operation .
*/
2005-06-27 20:07:45 +00:00
typedef struct Genesys_Model
{
SANE_String_Const name ;
SANE_String_Const vendor ;
SANE_String_Const model ;
2019-04-22 21:55:44 +00:00
SANE_Int model_id ;
2005-06-27 20:07:45 +00:00
SANE_Int asic_type ; /* ASIC type gl646 or gl841 */
Genesys_Command_Set * cmd_set ; /* pointers to low level functions */
SANE_Int xdpi_values [ MAX_RESOLUTIONS ] ; /* possible x resolutions */
SANE_Int ydpi_values [ MAX_RESOLUTIONS ] ; /* possible y resolutions */
SANE_Int bpp_gray_values [ MAX_DPI ] ; /* possible depths in gray mode */
SANE_Int bpp_color_values [ MAX_DPI ] ; /* possible depths in color mode */
2019-07-13 01:14:47 +00:00
// All offsets below are with respect to the sensor home position
2005-06-27 20:07:45 +00:00
SANE_Fixed x_offset ; /* Start of scan area in mm */
2013-12-16 04:45:31 +00:00
SANE_Fixed y_offset ; /* Start of scan area in mm (Amount of
2009-02-23 14:12:20 +00:00
feeding needed to get to the medium ) */
2005-06-27 20:07:45 +00:00
SANE_Fixed x_size ; /* Size of scan area in mm */
SANE_Fixed y_size ; /* Size of scan area in mm */
SANE_Fixed y_offset_calib ; /* Start of white strip in mm */
SANE_Fixed x_offset_mark ; /* Start of black mark in mm */
SANE_Fixed x_offset_ta ; /* Start of scan area in TA mode in mm */
SANE_Fixed y_offset_ta ; /* Start of scan area in TA mode in mm */
SANE_Fixed x_size_ta ; /* Size of scan area in TA mode in mm */
SANE_Fixed y_size_ta ; /* Size of scan area in TA mode in mm */
2019-07-13 01:14:47 +00:00
// The position of the sensor when it's aligned with the lamp for transparency scanning
2019-07-13 01:14:40 +00:00
SANE_Fixed y_offset_sensor_to_ta ;
2005-06-27 20:07:45 +00:00
SANE_Fixed y_offset_calib_ta ; /* Start of white strip in TA mode in mm */
2009-02-23 14:12:20 +00:00
SANE_Fixed post_scan ; /* Size of scan area after paper sensor stops
sensing document in mm */
2013-12-16 04:45:31 +00:00
SANE_Fixed eject_feed ; /* Amount of feeding needed to eject document
2009-02-23 14:12:20 +00:00
after finishing scanning in mm */
2005-06-27 20:07:45 +00:00
/* Line-distance correction (in pixel at optical_ydpi) for CCD scanners */
SANE_Int ld_shift_r ; /* red */
SANE_Int ld_shift_g ; /* green */
SANE_Int ld_shift_b ; /* blue */
Genesys_Color_Order line_mode_color_order ; /* Order of the CCD/CIS colors */
SANE_Bool is_cis ; /* Is this a CIS or CCD scanner? */
2009-01-19 05:46:43 +00:00
SANE_Bool is_sheetfed ; /* Is this sheetfed scanner? */
2005-06-27 20:07:45 +00:00
SANE_Int ccd_type ; /* which SENSOR type do we have ? */
SANE_Int dac_type ; /* which DAC do we have ? */
SANE_Int gpo_type ; /* General purpose output type */
SANE_Int motor_type ; /* stepper motor type */
SANE_Word flags ; /* Which hacks are needed for this scanner? */
2009-01-19 05:46:43 +00:00
SANE_Word buttons ; /* Button flags, described existing buttons for the model */
2005-06-27 20:07:45 +00:00
/*@} */
SANE_Int shading_lines ; /* how many lines are used for shading calibration */
2019-05-18 11:56:07 +00:00
SANE_Int shading_ta_lines ; // how many lines are used for shading calibration in TA mode
2005-06-27 20:07:45 +00:00
SANE_Int search_lines ; /* how many lines are used to search start position */
} Genesys_Model ;
2019-06-02 08:47:36 +00:00
struct Genesys_Settings
2005-06-27 20:07:45 +00:00
{
2019-06-08 11:03:53 +00:00
ScanMethod scan_method = ScanMethod : : FLATBED ;
2019-06-08 11:03:57 +00:00
ScanColorMode scan_mode = ScanColorMode : : LINEART ;
2019-06-08 11:03:53 +00:00
2019-06-02 08:47:36 +00:00
// horizontal dpi
int xres = 0 ;
// vertical dpi
int yres = 0 ;
//x start on scan table in mm
double tl_x = 0 ;
// y start on scan table in mm
double tl_y = 0 ;
// number of lines at scan resolution
unsigned int lines = 0 ;
// number of pixels at scan resolution
unsigned int pixels = 0 ;
// bit depth of the scan
unsigned int depth = 0 ;
2019-06-08 11:04:16 +00:00
ColorFilter color_filter = ColorFilter : : NONE ;
2010-01-12 05:17:09 +00:00
2019-06-02 08:47:36 +00:00
// true if scan is true gray, false if monochrome scan
int true_gray = 0 ;
2006-03-27 14:41:30 +00:00
2019-06-02 08:47:36 +00:00
// lineart threshold
int threshold = 0 ;
2006-06-07 22:39:09 +00:00
2019-06-02 08:47:36 +00:00
// lineart threshold curve for dynamic rasterization
int threshold_curve = 0 ;
2010-01-20 20:48:27 +00:00
2019-06-02 08:47:36 +00:00
// Disable interpolation for xres<yres
int disable_interpolation = 0 ;
2010-01-19 05:56:18 +00:00
2019-06-02 08:47:36 +00:00
// true is lineart is generated from gray data by the dynamic rasterization algoright
int dynamic_lineart = 0 ;
2013-08-11 19:15:25 +00:00
2019-06-02 08:47:36 +00:00
// value for contrast enhancement in the [-100..100] range
int contrast = 0 ;
2013-08-11 19:15:25 +00:00
2019-06-02 08:47:36 +00:00
// value for brightness enhancement in the [-100..100] range
int brightness = 0 ;
2017-05-27 05:27:22 +00:00
2019-06-02 08:47:36 +00:00
// cache entries expiration time
int expiration_time = 0 ;
} ;
2005-06-27 20:07:45 +00:00
2019-06-08 11:04:02 +00:00
struct SetupParams {
2019-06-08 11:04:14 +00:00
static constexpr unsigned NOT_SET = std : : numeric_limits < unsigned > : : max ( ) ;
2019-06-08 11:04:02 +00:00
// resolution in x direction
2019-06-08 11:04:14 +00:00
unsigned xres = NOT_SET ;
2019-06-08 11:04:02 +00:00
// resolution in y direction
2019-06-08 11:04:14 +00:00
unsigned yres = NOT_SET ;
2019-06-08 11:04:02 +00:00
// start pixel in X direction, from dummy_pixel + 1
float startx = - 1 ;
// start pixel in Y direction, counted according to base_ydpi
float starty = - 1 ;
2019-07-06 18:02:27 +00:00
// the number of pixels in X direction. Note that each logical pixel may correspond to more
// than one CCD pixel, see CKSEL and GenesysSensor::ccd_pixels_per_system_pixel()
2019-06-08 11:04:14 +00:00
unsigned pixels = NOT_SET ;
2019-06-08 11:04:02 +00:00
// the number of pixels in Y direction
2019-06-08 11:04:14 +00:00
unsigned lines = NOT_SET ;
2019-06-08 11:04:02 +00:00
// the depth of the scan in bits. Allowed are 1, 8, 16
2019-06-08 11:04:14 +00:00
unsigned depth = NOT_SET ;
2019-06-08 11:04:02 +00:00
// the number of channels
2019-06-08 11:04:14 +00:00
unsigned channels = NOT_SET ;
2019-06-08 11:04:02 +00:00
2019-06-08 11:04:22 +00:00
ScanMethod scan_method = static_cast < ScanMethod > ( NOT_SET ) ;
2019-06-08 11:04:14 +00:00
ScanColorMode scan_mode = static_cast < ScanColorMode > ( NOT_SET ) ;
2019-06-08 11:04:02 +00:00
2019-06-08 11:04:16 +00:00
ColorFilter color_filter = static_cast < ColorFilter > ( NOT_SET ) ;
2019-06-08 11:04:02 +00:00
2019-06-08 11:04:14 +00:00
unsigned flags = NOT_SET ;
2019-06-08 11:04:02 +00:00
void assert_valid ( ) const
{
2019-06-08 11:04:14 +00:00
if ( xres = = NOT_SET | | yres = = NOT_SET | | startx < 0 | | starty < 0 | |
pixels = = NOT_SET | | lines = = NOT_SET | | depth = = NOT_SET | | channels = = NOT_SET | |
2019-06-08 11:04:22 +00:00
scan_method = = static_cast < ScanMethod > ( NOT_SET ) | |
2019-06-08 11:04:16 +00:00
scan_mode = = static_cast < ScanColorMode > ( NOT_SET ) | |
color_filter = = static_cast < ColorFilter > ( NOT_SET ) | |
2019-06-08 11:04:14 +00:00
flags = = NOT_SET )
2019-06-08 11:04:02 +00:00
{
2019-06-08 11:04:14 +00:00
throw std : : runtime_error ( " SetupParams are not valid " ) ;
2019-06-08 11:04:02 +00:00
}
}
2019-07-22 23:00:44 +00:00
bool operator = = ( const SetupParams & other ) const
{
return xres = = other . xres & &
yres = = other . yres & &
startx = = other . startx & &
starty = = other . starty & &
pixels = = other . pixels & &
lines = = other . lines & &
depth = = other . depth & &
channels = = other . channels & &
scan_method = = other . scan_method & &
scan_mode = = other . scan_mode & &
color_filter = = other . color_filter & &
flags = = other . flags ;
}
2019-06-08 11:04:02 +00:00
} ;
2019-07-22 23:00:42 +00:00
template < class Stream >
void serialize ( Stream & str , SetupParams & x )
{
serialize ( str , x . xres ) ;
serialize ( str , x . yres ) ;
serialize ( str , x . startx ) ;
serialize ( str , x . starty ) ;
serialize ( str , x . pixels ) ;
serialize ( str , x . lines ) ;
serialize ( str , x . depth ) ;
serialize ( str , x . channels ) ;
serialize ( str , x . scan_method ) ;
serialize ( str , x . scan_mode ) ;
serialize ( str , x . color_filter ) ;
serialize ( str , x . flags ) ;
}
2019-06-02 08:47:35 +00:00
struct Genesys_Current_Setup
2005-11-19 22:51:01 +00:00
{
2019-06-08 11:04:21 +00:00
// params used for this setup
SetupParams params ;
2019-06-02 08:47:35 +00:00
// pixel count expected from scanner
int pixels = 0 ;
// line count expected from scanner
int lines = 0 ;
// depth expected from scanner
int depth = 0 ;
// channel count expected from scanner
int channels = 0 ;
2019-06-08 11:03:53 +00:00
2019-06-02 08:47:35 +00:00
// used exposure time
int exposure_time = 0 ;
// used xres
float xres = 0 ;
// used yres
float yres = 0 ;
// half ccd mode
2019-06-02 08:47:54 +00:00
unsigned ccd_size_divisor = 1 ;
2019-06-02 08:47:35 +00:00
SANE_Int stagger = 0 ;
// max shift of any ccd component, including staggered pixels
SANE_Int max_shift = 0 ;
2019-07-22 23:00:44 +00:00
bool operator = = ( const Genesys_Current_Setup & other ) const
{
return params = = other . params & &
pixels = = other . pixels & &
lines = = other . lines & &
depth = = other . depth & &
channels = = other . channels & &
exposure_time = = other . exposure_time & &
xres = = other . xres & &
yres = = other . yres & &
ccd_size_divisor = = other . ccd_size_divisor & &
stagger = = other . stagger & &
max_shift = = other . max_shift ;
}
2019-06-02 08:47:35 +00:00
} ;
2005-11-19 22:51:01 +00:00
2019-07-22 23:00:42 +00:00
template < class Stream >
void serialize ( Stream & str , Genesys_Current_Setup & x )
{
serialize ( str , x . params ) ;
serialize_newline ( str ) ;
serialize ( str , x . pixels ) ;
serialize ( str , x . lines ) ;
serialize ( str , x . depth ) ;
serialize ( str , x . channels ) ;
serialize ( str , x . exposure_time ) ;
serialize ( str , x . xres ) ;
serialize ( str , x . yres ) ;
serialize ( str , x . ccd_size_divisor ) ;
serialize ( str , x . stagger ) ;
serialize ( str , x . max_shift ) ;
}
2019-05-25 08:15:36 +00:00
struct Genesys_Buffer
2005-11-19 22:51:01 +00:00
{
2019-05-25 08:15:36 +00:00
Genesys_Buffer ( ) = default ;
size_t size ( ) const { return buffer_ . size ( ) ; }
size_t avail ( ) const { return avail_ ; }
size_t pos ( ) const { return pos_ ; }
// TODO: refactor code that uses this function to no longer use it
void set_pos ( size_t pos ) { pos_ = pos ; }
void alloc ( size_t size ) ;
void clear ( ) ;
void reset ( ) ;
uint8_t * get_write_pos ( size_t size ) ;
uint8_t * get_read_pos ( ) ; // TODO: mark as const
void produce ( size_t size ) ;
void consume ( size_t size ) ;
private :
std : : vector < uint8_t > buffer_ ;
// current position in read buffer
size_t pos_ = 0 ;
// data bytes currently in buffer
size_t avail_ = 0 ;
} ;
2005-06-27 20:07:45 +00:00
2009-03-25 12:57:24 +00:00
struct Genesys_Calibration_Cache
{
2019-05-25 08:15:32 +00:00
Genesys_Calibration_Cache ( ) = default ;
~ Genesys_Calibration_Cache ( ) = default ;
2009-03-25 12:57:24 +00:00
2019-05-25 08:15:32 +00:00
// used to check if entry is compatible
2019-06-02 08:47:40 +00:00
Genesys_Current_Setup used_setup ;
2019-05-25 08:15:32 +00:00
time_t last_calibration = 0 ;
2009-03-25 12:57:24 +00:00
2019-06-02 08:47:40 +00:00
Genesys_Frontend frontend ;
2019-05-25 08:15:32 +00:00
Genesys_Sensor sensor ;
2009-03-25 12:57:24 +00:00
2019-05-25 08:15:32 +00:00
size_t calib_pixels = 0 ;
size_t calib_channels = 0 ;
size_t average_size = 0 ;
2019-05-25 08:15:33 +00:00
std : : vector < uint8_t > white_average_data ;
std : : vector < uint8_t > dark_average_data ;
2019-07-22 23:00:44 +00:00
bool operator = = ( const Genesys_Calibration_Cache & other ) const
{
return used_setup = = other . used_setup & &
last_calibration = = other . last_calibration & &
frontend = = other . frontend & &
sensor = = other . sensor & &
calib_pixels = = other . calib_pixels & &
calib_channels = = other . calib_channels & &
average_size = = other . average_size & &
white_average_data = = other . white_average_data & &
dark_average_data = = other . dark_average_data ;
}
2009-03-25 12:57:24 +00:00
} ;
2019-07-22 23:00:42 +00:00
template < class Stream >
void serialize ( Stream & str , Genesys_Calibration_Cache & x )
{
serialize ( str , x . used_setup ) ;
serialize_newline ( str ) ;
serialize ( str , x . last_calibration ) ;
serialize_newline ( str ) ;
serialize ( str , x . frontend ) ;
serialize_newline ( str ) ;
serialize ( str , x . sensor ) ;
serialize_newline ( str ) ;
serialize ( str , x . calib_pixels ) ;
serialize ( str , x . calib_channels ) ;
serialize ( str , x . average_size ) ;
serialize_newline ( str ) ;
serialize ( str , x . white_average_data ) ;
serialize_newline ( str ) ;
serialize ( str , x . dark_average_data ) ;
}
2011-09-23 18:02:54 +00:00
/**
* Describes the current device status for the backend
* session . This should be more accurately called
* Genesys_Session .
*/
2005-06-27 20:07:45 +00:00
struct Genesys_Device
{
2019-05-25 08:15:28 +00:00
Genesys_Device ( ) = default ;
~ Genesys_Device ( ) ;
2019-07-22 23:00:42 +00:00
using Calibration = std : : vector < Genesys_Calibration_Cache > ;
2019-05-25 08:15:28 +00:00
// frees commonly used data
void clear ( ) ;
2019-07-05 23:10:07 +00:00
UsbDevice usb_dev ;
2019-05-25 08:15:28 +00:00
SANE_Word vendorId = 0 ; /**< USB vendor identifier */
SANE_Word productId = 0 ; /**< USB product identifier */
// USB mode:
// 0: not set
// 1: USB 1.1
// 2: USB 2.0
SANE_Int usb_mode = 0 ;
SANE_String file_name = nullptr ;
2019-05-25 08:15:42 +00:00
std : : string calib_file ;
2019-05-25 08:15:28 +00:00
// if enabled, no calibration data will be loaded or saved to files
SANE_Int force_calibration = 0 ;
2019-07-13 01:14:45 +00:00
// if enabled, will ignore the scan offsets and start scanning at true origin. This allows
// acquiring the positions of the black and white strips and the actual scan area
bool ignore_offsets = false ;
2019-05-25 08:15:28 +00:00
Genesys_Model * model = nullptr ;
2019-06-02 08:47:26 +00:00
Genesys_Register_Set reg ;
Genesys_Register_Set calib_reg ;
2019-06-02 08:47:40 +00:00
Genesys_Settings settings ;
2019-06-02 08:48:02 +00:00
Genesys_Frontend frontend , frontend_initial ;
2019-06-02 08:47:40 +00:00
Genesys_Gpo gpo ;
2019-06-02 08:47:38 +00:00
Genesys_Motor motor ;
2019-05-25 08:15:28 +00:00
uint8_t control [ 6 ] = { } ;
time_t init_date = 0 ;
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 ;
2019-05-18 11:55:59 +00:00
// bytes to read from USB when calibrating. If 0, this is not set
size_t calib_total_bytes_to_read = 0 ;
2019-06-02 08:47:59 +00:00
// 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 ;
2019-05-25 08:15:30 +00:00
2019-06-02 08:47:50 +00:00
// gamma overrides. If a respective array is not empty then it means that the gamma for that
// color is overridden.
std : : vector < uint16_t > gamma_override_tables [ 3 ] ;
2019-05-25 08:15:30 +00:00
std : : vector < uint8_t > white_average_data ;
std : : vector < uint8_t > dark_average_data ;
2019-05-25 08:15:28 +00:00
uint16_t dark [ 3 ] = { } ;
SANE_Bool already_initialized = 0 ;
SANE_Int scanhead_position_in_steps = 0 ;
SANE_Int lamp_off_time = 0 ;
SANE_Bool read_active = 0 ;
// signal wether the park command has been issued
SANE_Bool parking = 0 ;
// for sheetfed scanner's, is TRUE when there is a document in the scanner
SANE_Bool document = 0 ;
2019-05-18 11:56:06 +00:00
SANE_Bool needs_home_ta = 0 ;
2019-05-25 08:15:36 +00:00
Genesys_Buffer read_buffer ;
Genesys_Buffer lines_buffer ;
Genesys_Buffer shrink_buffer ;
Genesys_Buffer out_buffer ;
2019-05-25 08:15:28 +00:00
// buffer for digital lineart from gray data
Genesys_Buffer binarize_buffer = { } ;
// local buffer for gray data during dynamix lineart
Genesys_Buffer local_buffer = { } ;
// bytes to read from scanner
size_t read_bytes_left = 0 ;
// total bytes read sent to frontend
size_t total_bytes_read = 0 ;
// total bytes read to be sent to frontend
size_t total_bytes_to_read = 0 ;
// asic's word per line
size_t wpl = 0 ;
// contains the real used values
2019-06-02 08:47:40 +00:00
Genesys_Current_Setup current_setup ;
2019-05-25 08:15:28 +00:00
// look up table used in dynamic rasterization
unsigned char lineart_lut [ 256 ] = { } ;
2019-07-22 23:00:42 +00:00
Calibration calibration_cache ;
2019-05-25 08:15:28 +00:00
// used red line-distance shift
SANE_Int ld_shift_r = 0 ;
// used green line-distance shift
SANE_Int ld_shift_g = 0 ;
// used blue line-distance shift
SANE_Int ld_shift_b = 0 ;
// number of segments composing the sensor
int segnb = 0 ;
// number of lines used in line interpolation
int line_interp = 0 ;
// number of scan lines used during scan
int line_count = 0 ;
// bytes per full scan widthline
size_t bpl = 0 ;
// bytes distance between an odd and an even pixel
size_t dist = 0 ;
// number of even pixels
size_t len = 0 ;
// current pixel position within sub window
size_t cur = 0 ;
// number of bytes to skip at start of line
size_t skip = 0 ;
// array describing the order of the sub-segments of the sensor
size_t * order = nullptr ;
// buffer to handle even/odd data
Genesys_Buffer oe_buffer = { } ;
// when true the scanned picture is first buffered to allow software image enhancements
SANE_Bool buffer_image = 0 ;
// image buffer where the scanned picture is stored
2019-05-25 08:15:41 +00:00
std : : vector < uint8_t > img_buffer ;
2019-05-25 08:15:28 +00:00
// binary logger file
FILE * binary = nullptr ;
2005-06-27 20:07:45 +00:00
} ;
typedef struct Genesys_USB_Device_Entry
{
SANE_Word vendor ; /**< USB vendor identifier */
SANE_Word product ; /**< USB product identifier */
Genesys_Model * model ; /**< Scanner model information */
} Genesys_USB_Device_Entry ;
2011-02-16 06:13:01 +00:00
/**
* structure for motor database
*/
typedef struct {
2012-10-24 19:28:42 +00:00
int motor_type ; /**< motor id */
int exposure ; /**< exposure for the slope table */
int step_type ; /**< default step type for given exposure */
2019-05-18 11:56:02 +00:00
uint32_t * table ; // 0-terminated slope table at full step (i.e. step_type == 0)
2011-02-16 06:13:01 +00:00
} Motor_Profile ;
2012-05-14 20:22:59 +00:00
# define FULL_STEP 0
# define HALF_STEP 1
# define QUARTER_STEP 2
# define EIGHTH_STEP 3
2011-02-16 06:13:01 +00:00
# define SLOPE_TABLE_SIZE 1024
# define SCAN_TABLE 0 /* table 1 at 0x4000 for gl124 */
# define BACKTRACK_TABLE 1 /* table 2 at 0x4800 for gl124 */
# define STOP_TABLE 2 /* table 3 at 0x5000 for gl124 */
# define FAST_TABLE 3 /* table 4 at 0x5800 for gl124 */
# define HOME_TABLE 4 /* table 5 at 0x6000 for gl124 */
2011-11-09 14:20:29 +00:00
# define SCAN_FLAG_SINGLE_LINE 0x001
# define SCAN_FLAG_DISABLE_SHADING 0x002
# define SCAN_FLAG_DISABLE_GAMMA 0x004
# define SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE 0x008
# define SCAN_FLAG_IGNORE_LINE_DISTANCE 0x010
# define SCAN_FLAG_USE_OPTICAL_RES 0x020
# define SCAN_FLAG_DISABLE_LAMP 0x040
# define SCAN_FLAG_DYNAMIC_LINEART 0x080
# define SCAN_FLAG_CALIBRATION 0x100
# define SCAN_FLAG_FEEDING 0x200
# define SCAN_FLAG_USE_XPA 0x400
2013-12-19 06:00:30 +00:00
# define SCAN_FLAG_ENABLE_LEDADD 0x800
2011-11-09 14:20:29 +00:00
# define MOTOR_FLAG_AUTO_GO_HOME 0x01
# define MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE 0x02
# define MOTOR_FLAG_FEED 0x04
# define MOTOR_FLAG_USE_XPA 0x08
2012-10-24 19:28:42 +00:00
/** @name "Optical flags" */
/*@{ optical flags available when setting up sensor for scan */
# define OPTICAL_FLAG_DISABLE_GAMMA 0x01 /**< disable gamma correction */
# define OPTICAL_FLAG_DISABLE_SHADING 0x02 /**< disable shading correction */
# define OPTICAL_FLAG_DISABLE_LAMP 0x04 /**< turn off lamp */
# define OPTICAL_FLAG_ENABLE_LEDADD 0x08 /**< enable true CIS gray by enabling LED addition */
# define OPTICAL_FLAG_DISABLE_DOUBLE 0x10 /**< disable automatic x-direction double data expansion */
# define OPTICAL_FLAG_STAGGER 0x20 /**< disable stagger correction */
# define OPTICAL_FLAG_USE_XPA 0x40 /**< use XPA lamp rather than regular one */
/*@} */
2011-08-22 05:01:18 +00:00
2005-06-27 20:07:45 +00:00
/*--------------------------------------------------------------------------*/
/* common functions needed by low level specific functions */
/*--------------------------------------------------------------------------*/
2019-06-02 08:47:26 +00:00
inline GenesysRegister * sanei_genesys_get_address ( Genesys_Register_Set * regs , uint16_t addr )
{
auto * ret = regs - > find_reg_address ( addr ) ;
if ( ret = = nullptr ) {
DBG ( DBG_error , " %s: failed to find address for register 0x%02x, crash expected ! \n " ,
__func__ , addr ) ;
}
return ret ;
}
2005-06-27 20:07:45 +00:00
2019-06-02 08:47:26 +00:00
inline uint8_t sanei_genesys_read_reg_from_set ( Genesys_Register_Set * regs , uint16_t address )
{
return regs - > get8 ( address ) ;
}
2005-06-27 20:07:45 +00:00
2019-06-02 08:47:26 +00:00
inline void sanei_genesys_set_reg_from_set ( Genesys_Register_Set * regs , uint16_t address ,
uint8_t value )
{
regs - > set8 ( address , value ) ;
}
2005-06-27 20:07:45 +00:00
2010-11-06 20:12:56 +00:00
extern SANE_Status sanei_genesys_init_cmd_set ( Genesys_Device * dev ) ;
2019-07-14 20:40:39 +00:00
extern void sanei_genesys_read_register ( Genesys_Device * dev , uint16_t reg , uint8_t * val ) ;
2005-06-27 20:07:45 +00:00
2019-07-14 20:40:41 +00:00
extern void sanei_genesys_write_register ( Genesys_Device * dev , uint16_t reg , uint8_t val ) ;
2005-06-27 20:07:45 +00:00
2019-07-14 20:40:35 +00:00
extern void sanei_genesys_read_hregister ( Genesys_Device * dev , uint16_t reg , uint8_t * val ) ;
2010-11-06 20:12:56 +00:00
2019-07-14 20:40:36 +00:00
extern void sanei_genesys_write_hregister ( Genesys_Device * dev , uint16_t reg , uint8_t val ) ;
2010-11-06 20:12:56 +00:00
2013-01-28 21:04:37 +00:00
extern SANE_Status
2019-06-02 08:47:26 +00:00
sanei_genesys_bulk_write_register ( Genesys_Device * dev ,
2019-06-08 11:03:56 +00:00
Genesys_Register_Set & regs ) ;
2013-01-28 21:04:37 +00:00
2019-07-14 20:40:37 +00:00
extern void sanei_genesys_write_0x8c ( Genesys_Device * dev , uint8_t index , uint8_t val ) ;
2010-11-06 20:12:56 +00:00
2019-05-11 09:05:17 +00:00
extern unsigned sanei_genesys_get_bulk_max_size ( Genesys_Device * dev ) ;
2019-07-14 20:40:34 +00:00
extern void sanei_genesys_bulk_read_data ( Genesys_Device * dev , uint8_t addr , uint8_t * data ,
size_t len ) ;
2019-05-11 09:05:09 +00:00
2019-05-11 09:05:18 +00:00
extern SANE_Status sanei_genesys_bulk_write_data ( Genesys_Device * dev , uint8_t addr , uint8_t * data ,
size_t len ) ;
2010-11-06 20:12:56 +00:00
extern SANE_Status sanei_genesys_get_status ( Genesys_Device * dev , uint8_t * status ) ;
extern void sanei_genesys_print_status ( uint8_t val ) ;
extern SANE_Status
2019-05-11 09:05:19 +00:00
sanei_genesys_write_ahb ( Genesys_Device * dev , uint32_t addr , uint32_t size , uint8_t * data ) ;
2005-06-27 20:07:45 +00:00
extern void sanei_genesys_init_structs ( Genesys_Device * dev ) ;
2019-06-02 08:47:51 +00:00
const Genesys_Sensor & sanei_genesys_find_sensor_any ( Genesys_Device * dev ) ;
Genesys_Sensor & sanei_genesys_find_sensor_any_for_write ( Genesys_Device * dev ) ;
2019-06-02 08:47:52 +00:00
const Genesys_Sensor & sanei_genesys_find_sensor ( Genesys_Device * dev , int dpi ,
2019-07-13 01:14:42 +00:00
ScanMethod scan_method ) ;
2019-06-02 08:47:52 +00:00
Genesys_Sensor & sanei_genesys_find_sensor_for_write ( Genesys_Device * dev , int dpi ,
2019-07-13 01:14:42 +00:00
ScanMethod scan_method ) ;
2019-06-02 08:47:51 +00:00
2005-06-27 20:07:45 +00:00
extern SANE_Status
2019-06-02 08:47:51 +00:00
sanei_genesys_init_shading_data ( Genesys_Device * dev , const Genesys_Sensor & sensor ,
int pixels_per_line ) ;
2005-06-27 20:07:45 +00:00
2009-01-19 05:46:43 +00:00
extern SANE_Status sanei_genesys_read_valid_words ( Genesys_Device * dev ,
unsigned int * steps ) ;
2009-12-09 19:52:29 +00:00
extern SANE_Status sanei_genesys_read_scancnt ( Genesys_Device * dev ,
unsigned int * steps ) ;
2005-06-27 20:07:45 +00:00
extern SANE_Status sanei_genesys_read_feed_steps ( Genesys_Device * dev ,
2005-11-19 22:51:01 +00:00
unsigned int * steps ) ;
2005-06-27 20:07:45 +00:00
2019-06-08 11:04:24 +00:00
void sanei_genesys_set_lamp_power ( Genesys_Device * dev , const Genesys_Sensor & sensor ,
Genesys_Register_Set & regs , bool set ) ;
2019-06-08 11:04:25 +00:00
void sanei_genesys_set_motor_power ( Genesys_Register_Set & regs , bool set ) ;
2005-06-27 20:07:45 +00:00
extern void
sanei_genesys_calculate_zmode2 ( SANE_Bool two_table ,
2009-02-26 03:15:43 +00:00
uint32_t exposure_time ,
uint16_t * slope_table ,
2005-06-27 20:07:45 +00:00
int reg21 ,
2009-02-26 03:15:43 +00:00
int move , int reg22 , uint32_t * z1 ,
uint32_t * z2 ) ;
2005-06-27 20:07:45 +00:00
extern void
2013-03-25 21:12:12 +00:00
sanei_genesys_calculate_zmode ( uint32_t exposure_time ,
2009-02-26 03:15:43 +00:00
uint32_t steps_sum ,
uint16_t last_speed , uint32_t feedl ,
uint8_t fastfed , uint8_t scanfed ,
uint8_t fwdstep , uint8_t tgtime ,
uint32_t * z1 , uint32_t * z2 ) ;
2005-06-27 20:07:45 +00:00
extern SANE_Status
2009-02-26 03:15:43 +00:00
sanei_genesys_set_buffer_address ( Genesys_Device * dev , uint32_t addr ) ;
2005-06-27 20:07:45 +00:00
2012-11-02 20:46:44 +00:00
/** @brief Reads data from frontend register.
* Reads data from the given frontend register . May be used to query
* analog frontend status by reading the right register .
*/
2010-06-23 16:21:36 +00:00
extern SANE_Status
sanei_genesys_fe_read_data ( Genesys_Device * dev , uint8_t addr ,
uint16_t * data ) ;
2012-11-02 20:46:44 +00:00
/** @brief Write data to frontend register.
* Writes data to analog frontend register at the given address .
* The use and address of registers change from model to model .
*/
2005-06-27 20:07:45 +00:00
extern SANE_Status
2009-02-26 03:15:43 +00:00
sanei_genesys_fe_write_data ( Genesys_Device * dev , uint8_t addr ,
uint16_t data ) ;
2005-06-27 20:07:45 +00:00
2005-11-19 22:51:01 +00:00
extern SANE_Int
sanei_genesys_exposure_time2 ( Genesys_Device * dev ,
float ydpi , int step_type , int endpixel ,
2007-11-22 14:05:13 +00:00
int led_exposure , int power_mode ) ;
2005-11-19 22:51:01 +00:00
2005-06-27 20:07:45 +00:00
extern SANE_Int
sanei_genesys_exposure_time ( Genesys_Device * dev , Genesys_Register_Set * reg ,
int xdpi ) ;
2009-01-19 05:46:43 +00:00
extern SANE_Int
2009-02-26 03:15:43 +00:00
sanei_genesys_generate_slope_table ( uint16_t * slope_table , unsigned int max_steps ,
unsigned int use_steps , uint16_t stop_at ,
uint16_t vstart , uint16_t vend ,
2009-01-19 05:46:43 +00:00
unsigned int steps , double g ,
unsigned int * used_steps , unsigned int * vfinal ) ;
2005-06-27 20:07:45 +00:00
extern SANE_Int
sanei_genesys_create_slope_table ( Genesys_Device * dev ,
2009-02-26 03:15:43 +00:00
uint16_t * slope_table , int steps ,
2005-06-27 20:07:45 +00:00
int step_type , int exposure_time ,
2007-11-22 14:05:13 +00:00
SANE_Bool same_speed , double yres ,
int power_mode ) ;
2005-06-27 20:07:45 +00:00
2005-11-19 22:51:01 +00:00
SANE_Int
sanei_genesys_create_slope_table3 ( Genesys_Device * dev ,
2009-02-26 03:15:43 +00:00
uint16_t * slope_table , int max_step ,
2005-11-19 22:51:01 +00:00
unsigned int use_steps ,
int step_type , int exposure_time ,
double yres ,
unsigned int * used_steps ,
2007-11-22 14:05:13 +00:00
unsigned int * final_exposure ,
int power_mode ) ;
2005-11-19 22:51:01 +00:00
2019-06-02 08:47:49 +00:00
void sanei_genesys_create_default_gamma_table ( Genesys_Device * dev ,
std : : vector < uint16_t > & gamma_table , float gamma ) ;
2019-06-02 08:47:50 +00:00
std : : vector < uint16_t > get_gamma_table ( Genesys_Device * dev , const Genesys_Sensor & sensor ,
int color ) ;
2019-06-02 08:47:51 +00:00
SANE_Status sanei_genesys_send_gamma_table ( Genesys_Device * dev , const Genesys_Sensor & sensor ) ;
2005-06-27 20:07:45 +00:00
extern SANE_Status sanei_genesys_start_motor ( Genesys_Device * dev ) ;
extern SANE_Status sanei_genesys_stop_motor ( Genesys_Device * dev ) ;
extern SANE_Status
2019-06-02 08:47:44 +00:00
sanei_genesys_search_reference_point ( Genesys_Device * dev , Genesys_Sensor & sensor ,
uint8_t * data ,
int start_pixel , int dpi , int width ,
int height ) ;
2005-06-27 20:07:45 +00:00
2019-05-24 18:13:37 +00:00
extern SANE_Status sanei_genesys_write_file ( const char * filename , uint8_t * data , size_t length ) ;
2019-05-11 09:12:29 +00:00
2005-06-27 20:07:45 +00:00
extern SANE_Status
2019-05-10 18:04:15 +00:00
sanei_genesys_write_pnm_file ( const char * filename , uint8_t * data , int depth ,
2005-06-27 20:07:45 +00:00
int channels , int pixels_per_line , int lines ) ;
extern SANE_Status
sanei_genesys_test_buffer_empty ( Genesys_Device * dev , SANE_Bool * empty ) ;
extern SANE_Status
2009-02-26 03:15:43 +00:00
sanei_genesys_read_data_from_scanner ( Genesys_Device * dev , uint8_t * data ,
2005-06-27 20:07:45 +00:00
size_t size ) ;
2019-06-02 08:47:26 +00:00
inline void sanei_genesys_set_double ( Genesys_Register_Set * regs , uint16_t addr , uint16_t value )
{
regs - > set16 ( addr , value ) ;
}
2010-11-06 20:12:56 +00:00
2019-06-02 08:47:26 +00:00
inline void sanei_genesys_set_triple ( Genesys_Register_Set * regs , uint16_t addr , uint32_t value )
{
regs - > set24 ( addr , value ) ;
}
2010-11-06 20:12:56 +00:00
2019-06-02 08:47:26 +00:00
inline void sanei_genesys_get_double ( Genesys_Register_Set * regs , uint16_t addr , uint16_t * value )
{
* value = regs - > get16 ( addr ) ;
}
2010-11-06 20:12:56 +00:00
2019-06-02 08:47:26 +00:00
inline void sanei_genesys_get_triple ( Genesys_Register_Set * regs , uint16_t addr , uint32_t * value )
{
* value = regs - > get24 ( addr ) ;
}
2005-06-27 20:07:45 +00:00
2019-06-02 08:47:31 +00:00
inline void sanei_genesys_set_exposure ( Genesys_Register_Set & regs , const SensorExposure & exposure )
{
regs . set8 ( 0x10 , ( exposure . red > > 8 ) & 0xff ) ;
regs . set8 ( 0x11 , exposure . red & 0xff ) ;
regs . set8 ( 0x12 , ( exposure . green > > 8 ) & 0xff ) ;
regs . set8 ( 0x13 , exposure . green & 0xff ) ;
regs . set8 ( 0x14 , ( exposure . blue > > 8 ) & 0xff ) ;
regs . set8 ( 0x15 , exposure . blue & 0xff ) ;
}
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 ) ;
return exposure ;
}
2011-01-12 19:51:32 +00:00
extern SANE_Status
sanei_genesys_wait_for_home ( Genesys_Device * dev ) ;
2013-01-28 21:04:37 +00:00
extern SANE_Status
sanei_genesys_asic_init ( Genesys_Device * dev , SANE_Bool cold ) ;
2019-06-02 08:47:51 +00:00
int sanei_genesys_compute_dpihw ( Genesys_Device * dev , const Genesys_Sensor & sensor , int xres ) ;
2011-01-24 05:22:14 +00:00
2019-06-02 08:47:51 +00:00
int sanei_genesys_compute_dpihw_calibration ( Genesys_Device * dev , const Genesys_Sensor & sensor ,
int xres ) ;
2019-05-18 11:56:12 +00:00
2011-02-16 06:13:01 +00:00
extern
Motor_Profile * sanei_genesys_get_motor_profile ( Motor_Profile * motors , int motor_type , int exposure ) ;
extern
int sanei_genesys_compute_step_type ( Motor_Profile * motors , int motor_type , int exposure ) ;
extern
int sanei_genesys_slope_table ( uint16_t * slope , int * steps , int dpi , int exposure , int base_dpi , int step_type , int factor , int motor_type , Motor_Profile * motors ) ;
2011-08-23 05:20:52 +00:00
/** @brief find lowest motor resolution for the device.
* Parses the resolution list for motor and
* returns the lowest value .
2012-10-24 19:28:42 +00:00
* @ param dev for which to find the lowest motor resolution
2011-08-23 05:20:52 +00:00
* @ return the lowest available motor resolution for the device
*/
2011-02-16 06:13:01 +00:00
extern
int sanei_genesys_get_lowest_ydpi ( Genesys_Device * dev ) ;
2011-08-23 05:20:52 +00:00
/** @brief find lowest resolution for the device.
* Parses the resolution list for motor and sensor and
* returns the lowest value .
2012-10-24 19:28:42 +00:00
* @ param dev for which to find the lowest resolution
2011-08-23 05:20:52 +00:00
* @ return the lowest available resolution for the device
*/
extern
int sanei_genesys_get_lowest_dpi ( Genesys_Device * dev ) ;
2019-06-30 11:05:16 +00:00
extern bool
2019-06-02 08:47:51 +00:00
sanei_genesys_is_compatible_calibration ( Genesys_Device * dev , const Genesys_Sensor & sensor ,
2011-07-31 20:09:46 +00:00
Genesys_Calibration_Cache * cache ,
int for_overwrite ) ;
2011-09-22 04:17:02 +00:00
/** @brief compute maximum line distance shift
* compute maximum line distance shift for the motor and sensor
* combination . Line distance shift is the distance between different
* color component of CCD sensors . Since these components aren ' t at
* the same physical place , they scan diffrent lines . Software must
* take this into account to accurately mix color data .
* @ param dev device session to compute max_shift for
* @ param channels number of color channels for the scan
* @ param yres motor resolution used for the scan
* @ param flags scan flags
* @ return 0 or line distance shift
*/
2013-01-28 21:04:37 +00:00
extern
2011-09-22 04:17:02 +00:00
int sanei_genesys_compute_max_shift ( Genesys_Device * dev ,
int channels ,
int yres ,
int flags ) ;
2013-08-11 19:15:25 +00:00
extern SANE_Status
sanei_genesys_load_lut ( unsigned char * lut ,
int in_bits ,
int out_bits ,
int out_min ,
int out_max ,
int slope ,
int offset ) ;
extern SANE_Status
sanei_genesys_generate_gamma_buffer ( Genesys_Device * dev ,
2019-06-02 08:47:51 +00:00
const Genesys_Sensor & sensor ,
2013-08-11 19:15:25 +00:00
int bits ,
int max ,
int size ,
uint8_t * gamma ) ;
2005-06-27 20:07:45 +00:00
/*---------------------------------------------------------------------------*/
/* ASIC specific functions declarations */
/*---------------------------------------------------------------------------*/
extern SANE_Status sanei_gl646_init_cmd_set ( Genesys_Device * dev ) ;
extern SANE_Status sanei_gl841_init_cmd_set ( Genesys_Device * dev ) ;
2010-07-20 20:04:11 +00:00
extern SANE_Status sanei_gl843_init_cmd_set ( Genesys_Device * dev ) ;
2013-01-28 21:04:37 +00:00
extern SANE_Status sanei_gl846_init_cmd_set ( Genesys_Device * dev ) ;
2010-04-25 19:32:44 +00:00
extern SANE_Status sanei_gl847_init_cmd_set ( Genesys_Device * dev ) ;
2010-11-06 20:12:56 +00:00
extern SANE_Status sanei_gl124_init_cmd_set ( Genesys_Device * dev ) ;
2005-06-27 20:07:45 +00:00
2019-05-11 09:12:28 +00:00
// same as usleep, except that it does nothing if testing mode is enabled
extern void sanei_genesys_usleep ( unsigned int useconds ) ;
// same as sanei_genesys_usleep just that the duration is in milliseconds
extern void sanei_genesys_sleep_ms ( unsigned int milliseconds ) ;
2019-05-25 08:15:26 +00:00
void add_function_to_run_at_backend_exit ( std : : function < void ( ) > function ) ;
// calls functions added via add_function_to_run_at_backend_exit() in reverse order of being
// added.
void run_functions_at_backend_exit ( ) ;
template < class T >
class StaticInit {
public :
StaticInit ( ) = default ;
StaticInit ( const StaticInit & ) = delete ;
StaticInit & operator = ( const StaticInit & ) = delete ;
template < class . . . Args >
void init ( Args & & . . . args )
{
ptr_ = std : : unique_ptr < T > ( new T ( std : : forward < Args > ( args ) . . . ) ) ;
add_function_to_run_at_backend_exit ( [ this ] ( ) { deinit ( ) ; } ) ;
}
void deinit ( )
{
ptr_ . release ( ) ;
}
const T * operator - > ( ) const { return ptr_ . get ( ) ; }
T * operator - > ( ) { return ptr_ . get ( ) ; }
const T & operator * ( ) const { return * ptr_ . get ( ) ; }
T & operator * ( ) { return * ptr_ . get ( ) ; }
private :
std : : unique_ptr < T > ptr_ ;
} ;
2019-05-25 08:15:27 +00:00
extern StaticInit < std : : vector < Genesys_Sensor > > s_sensors ;
void genesys_init_sensor_tables ( ) ;
2019-06-02 08:48:03 +00:00
void genesys_init_frontend_tables ( ) ;
2019-05-25 08:15:27 +00:00
2019-06-08 11:03:59 +00:00
void debug_dump ( unsigned level , const Genesys_Settings & settings ) ;
2019-06-08 11:04:13 +00:00
void debug_dump ( unsigned level , const SetupParams & params ) ;
2019-06-30 11:05:22 +00:00
void debug_dump ( unsigned level , const Genesys_Current_Setup & setup ) ;
2019-07-06 18:02:23 +00:00
void debug_dump ( unsigned level , const Genesys_Register_Set & regs ) ;
2019-06-08 11:03:59 +00:00
2005-06-27 20:07:45 +00:00
# endif /* not GENESYS_LOW_H */