2006-12-02 14:47:21 +00:00
/*
* epson2 . c - SANE library for Epson scanners .
*
* Based on Kazuhiro Sasayama previous
* Work on epson . [ ch ] file from the SANE package .
2006-12-18 00:13:09 +00:00
* Please see those files for additional copyrights .
2006-12-02 14:47:21 +00:00
*
2007-11-18 09:36:04 +00:00
* Copyright ( C ) 2006 - 07 Tower Technologies
2006-12-02 14:47:21 +00:00
* Author : Alessandro Zummo < a . zummo @ towertech . it >
*
* 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 , version 2.
*/
2008-12-26 22:02:32 +00:00
# define EPSON2_VERSION 1
# define EPSON2_REVISION 0
2009-06-15 23:07:26 +00:00
# define EPSON2_BUILD 122
2006-12-02 14:47:21 +00:00
/* debugging levels:
*
2008-01-09 17:10:08 +00:00
* 127 e2_recv buffer
* 125 e2_send buffer
2009-06-16 14:24:43 +00:00
* 32 more network progression
2009-06-01 14:18:52 +00:00
* 24 network header
2009-06-03 16:52:59 +00:00
* 23 network info
2006-12-02 14:47:21 +00:00
* 20 usb cmd counters
2006-12-18 00:13:09 +00:00
* 18 sane_read
2009-06-03 16:52:59 +00:00
* 17 setvalue , getvalue , control_option
2008-01-09 17:10:08 +00:00
* 15 e2_send , e2_recv calls
* 13 e2_cmd_info_block
2006-12-02 14:47:21 +00:00
* 12 epson_cmd_simple
2008-01-09 17:10:08 +00:00
* 11 even more
* 10 more debug in ESC / I commands
* 9 ESC x / FS x in e2_send
* 8 ESC / I commands
* 7 open / close / attach
* 6 print_params
* 5 basic functions
2006-12-02 14:47:21 +00:00
* 3 status information
* 1 scanner info and capabilities
* warnings
*/
2009-06-01 14:18:52 +00:00
# include "sane/config.h"
2006-12-02 14:47:21 +00:00
2006-12-18 00:13:09 +00:00
# include "epson2.h"
2006-12-02 14:47:21 +00:00
# include <limits.h>
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <ctype.h>
# include <fcntl.h>
# include <unistd.h>
# include <errno.h>
2008-02-02 21:18:13 +00:00
# include <sys/time.h>
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
# include "sane/saneopts.h"
# include "sane/sanei_scsi.h"
# include "sane/sanei_usb.h"
# include "sane/sanei_pio.h"
# include "sane/sanei_tcp.h"
# include "sane/sanei_udp.h"
# include "sane/sanei_backend.h"
# include "sane/sanei_config.h"
2006-12-02 14:47:21 +00:00
2006-12-18 00:13:09 +00:00
# include "epson2-io.h"
# include "epson2-commands.h"
2009-06-01 14:18:52 +00:00
# include "epson2-ops.h"
2006-12-18 00:13:09 +00:00
2006-12-02 14:47:21 +00:00
# include "epson2_scsi.h"
# include "epson_usb.h"
# include "epson2_net.h"
/*
* Definition of the mode_param struct , that is used to
* specify the valid parameters for the different scan modes .
*
* The depth variable gets updated when the bit depth is modified .
*/
2009-06-01 14:18:52 +00:00
struct mode_param mode_params [ ] = {
2006-12-02 14:47:21 +00:00
{ 0 , 0x00 , 0x30 , 1 } ,
{ 0 , 0x00 , 0x30 , 8 } ,
{ 1 , 0x02 , 0x00 , 8 }
} ;
static const SANE_String_Const mode_list [ ] = {
2009-06-15 22:38:24 +00:00
" Binary " ,
" Gray " ,
" Color " ,
2006-12-02 14:47:21 +00:00
NULL
} ;
static const SANE_String_Const adf_mode_list [ ] = {
2009-06-15 22:38:24 +00:00
" Simplex " ,
" Duplex " ,
2006-12-02 14:47:21 +00:00
NULL
} ;
/*
* source list need one dummy entry ( save device settings is crashing ) .
* NOTE : no const - this list gets created while exploring the capabilities
* of the scanner .
*/
2009-06-01 14:18:52 +00:00
SANE_String_Const source_list [ ] = {
2006-12-02 14:47:21 +00:00
FBF_STR ,
NULL ,
NULL ,
NULL
} ;
static const SANE_String_Const film_list [ ] = {
2009-06-15 22:38:24 +00:00
" Positive Film " ,
" Negative Film " ,
" Positive Slide " ,
" Negative Slide " ,
2006-12-02 14:47:21 +00:00
NULL
} ;
static const SANE_String_Const focus_list [ ] = {
2009-06-15 22:38:24 +00:00
" Focus on glass " ,
" Focus 2.5mm above glass " ,
2006-12-02 14:47:21 +00:00
NULL
} ;
# define HALFTONE_NONE 0x01
# define HALFTONE_TET 0x03
2009-06-01 14:18:52 +00:00
const int halftone_params [ ] = {
2006-12-02 14:47:21 +00:00
HALFTONE_NONE ,
0x00 ,
0x10 ,
0x20 ,
0x80 ,
0x90 ,
0xa0 ,
0xb0 ,
HALFTONE_TET ,
0xc0 ,
0xd0
} ;
static const SANE_String_Const halftone_list [ ] = {
2009-06-15 22:38:24 +00:00
" None " ,
" Halftone A (Hard Tone) " ,
" Halftone B (Soft Tone) " ,
" Halftone C (Net Screen) " ,
2006-12-02 14:47:21 +00:00
NULL
} ;
static const SANE_String_Const halftone_list_4 [ ] = {
2009-06-15 22:38:24 +00:00
" None " ,
" Halftone A (Hard Tone) " ,
" Halftone B (Soft Tone) " ,
" Halftone C (Net Screen) " ,
" Dither A (4x4 Bayer) " ,
" Dither B (4x4 Spiral) " ,
" Dither C (4x4 Net Screen) " ,
" Dither D (8x4 Net Screen) " ,
2006-12-02 14:47:21 +00:00
NULL
} ;
static const SANE_String_Const halftone_list_7 [ ] = {
2009-06-15 22:38:24 +00:00
" None " ,
" Halftone A (Hard Tone) " ,
" Halftone B (Soft Tone) " ,
" Halftone C (Net Screen) " ,
" Dither A (4x4 Bayer) " ,
" Dither B (4x4 Spiral) " ,
" Dither C (4x4 Net Screen) " ,
" Dither D (8x4 Net Screen) " ,
" Text Enhanced Technology " ,
" Download pattern A " ,
" Download pattern B " ,
2006-12-02 14:47:21 +00:00
NULL
} ;
static const SANE_String_Const dropout_list [ ] = {
2009-06-15 22:38:24 +00:00
" None " ,
" Red " ,
" Green " ,
" Blue " ,
2006-12-02 14:47:21 +00:00
NULL
} ;
static const SANE_Bool color_userdefined [ ] = {
SANE_FALSE ,
SANE_TRUE ,
SANE_FALSE ,
SANE_FALSE ,
SANE_FALSE ,
SANE_FALSE
} ;
static const SANE_String_Const color_list [ ] = {
2009-06-15 22:38:24 +00:00
" No Correction " ,
" User defined " ,
" Impact-dot printers " ,
" Thermal printers " ,
" Ink-jet printers " ,
" CRT monitors " ,
2006-12-02 14:47:21 +00:00
NULL
} ;
/*
* Gamma correction :
2009-06-03 00:28:44 +00:00
* The A and B level scanners work differently than the D level scanners ,
* therefore I define two different sets of arrays , plus one set of
* variables that get set to the actally used params and list arrays at runtime .
2006-12-02 14:47:21 +00:00
*/
2009-06-03 00:28:44 +00:00
2006-12-02 14:47:21 +00:00
static int gamma_params_ab [ ] = {
0x01 ,
0x03 ,
0x00 ,
0x10 ,
0x20
} ;
static const SANE_String_Const gamma_list_ab [ ] = {
2009-06-15 22:38:24 +00:00
" Default " ,
" User defined " ,
" High density printing " ,
" Low density printing " ,
" High contrast printing " ,
2006-12-02 14:47:21 +00:00
NULL
} ;
static SANE_Bool gamma_userdefined_ab [ ] = {
SANE_FALSE ,
SANE_TRUE ,
SANE_FALSE ,
SANE_FALSE ,
SANE_FALSE ,
} ;
static int gamma_params_d [ ] = {
0x03 ,
0x04
} ;
static const SANE_String_Const gamma_list_d [ ] = {
2009-06-15 22:38:24 +00:00
" User defined (Gamma=1.0) " ,
" User defined (Gamma=1.8) " ,
2006-12-02 14:47:21 +00:00
NULL
} ;
static SANE_Bool gamma_userdefined_d [ ] = {
SANE_TRUE ,
SANE_TRUE
} ;
static SANE_Bool * gamma_userdefined ;
2009-06-01 14:18:52 +00:00
int * gamma_params ;
2006-12-02 14:47:21 +00:00
/* Bay list:
* this is used for the FilmScan
* XXX Add APS loader support
*/
static const SANE_String_Const bay_list [ ] = {
2007-01-20 20:59:05 +00:00
" 1 " ,
" 2 " ,
" 3 " ,
" 4 " ,
" 5 " ,
" 6 " ,
2006-12-02 14:47:21 +00:00
NULL
} ;
/* minimum, maximum, quantization */
static const SANE_Range u8_range = { 0 , 255 , 0 } ;
static const SANE_Range s8_range = { - 127 , 127 , 0 } ;
static const SANE_Range outline_emphasis_range = { - 2 , 2 , 0 } ;
/*
* List of pointers to devices - will be dynamically allocated depending
* on the number of devices found .
*/
2009-06-03 00:28:44 +00:00
static const SANE_Device * * devlist ;
2006-12-02 14:47:21 +00:00
/* Some utility functions */
static size_t
max_string_size ( const SANE_String_Const strings [ ] )
{
size_t size , max_size = 0 ;
int i ;
for ( i = 0 ; strings [ i ] ; i + + ) {
size = strlen ( strings [ i ] ) + 1 ;
if ( size > max_size )
max_size = size ;
}
return max_size ;
}
static SANE_Status attach_one_usb ( SANE_String_Const devname ) ;
static SANE_Status attach_one_net ( SANE_String_Const devname ) ;
2009-06-03 00:28:44 +00:00
static void filter_resolution_list ( Epson_Scanner * s ) ;
2006-12-02 14:47:21 +00:00
static void
print_params ( const SANE_Parameters params )
{
2009-06-01 14:18:52 +00:00
DBG ( 6 , " params.format = %d \n " , params . format ) ;
DBG ( 6 , " params.last_frame = %d \n " , params . last_frame ) ;
DBG ( 6 , " params.bytes_per_line = %d \n " , params . bytes_per_line ) ;
2008-01-09 17:10:08 +00:00
DBG ( 6 , " params.pixels_per_line = %d \n " , params . pixels_per_line ) ;
2009-06-01 14:18:52 +00:00
DBG ( 6 , " params.lines = %d \n " , params . lines ) ;
DBG ( 6 , " params.depth = %d \n " , params . depth ) ;
2006-12-02 14:47:21 +00:00
}
2006-12-18 00:13:09 +00:00
/*
* close_scanner ( )
*
* Close the open scanner . Depending on the connection method , a different
* close function is called .
*/
2006-12-02 14:47:21 +00:00
2006-12-18 00:13:09 +00:00
static void
2009-06-03 00:28:44 +00:00
close_scanner ( Epson_Scanner * s )
2006-12-02 14:47:21 +00:00
{
2008-01-09 17:10:08 +00:00
DBG ( 7 , " %s: fd = %d \n " , __func__ , s - > fd ) ;
2006-12-02 14:47:21 +00:00
2006-12-18 00:13:09 +00:00
if ( s - > fd = = - 1 )
return ;
2006-12-02 14:47:21 +00:00
2006-12-18 00:13:09 +00:00
/* send a request_status. This toggles w_cmd_count and r_cmd_count */
if ( r_cmd_count % 2 )
2008-01-09 17:10:08 +00:00
esci_request_status ( s , NULL ) ;
2006-12-02 14:47:21 +00:00
2006-12-18 00:13:09 +00:00
/* request extended status. This toggles w_cmd_count only */
2009-06-03 00:28:44 +00:00
if ( w_cmd_count % 2 )
2008-01-09 17:10:08 +00:00
esci_request_extended_status ( s , NULL , NULL ) ;
2006-12-02 14:47:21 +00:00
2006-12-18 00:13:09 +00:00
if ( s - > hw - > connection = = SANE_EPSON_NET ) {
sanei_epson_net_unlock ( s ) ;
sanei_tcp_close ( s - > fd ) ;
} else if ( s - > hw - > connection = = SANE_EPSON_SCSI ) {
sanei_scsi_close ( s - > fd ) ;
} else if ( s - > hw - > connection = = SANE_EPSON_PIO ) {
sanei_pio_close ( s - > fd ) ;
} else if ( s - > hw - > connection = = SANE_EPSON_USB ) {
sanei_usb_close ( s - > fd ) ;
}
2006-12-02 14:47:21 +00:00
2006-12-18 00:13:09 +00:00
s - > fd = - 1 ;
2006-12-02 14:47:21 +00:00
}
2007-12-26 11:34:17 +00:00
static void
2008-01-09 17:10:08 +00:00
e2_network_discovery ( void )
2007-12-26 11:34:17 +00:00
{
fd_set rfds ;
2008-01-09 17:10:08 +00:00
int fd , len ;
2007-12-26 11:34:17 +00:00
SANE_Status status ;
char * ip , * query = " EPSONP \x00 \xff \x00 \x00 \x00 \x00 \x00 \x00 \x00 " ;
2009-06-01 14:18:52 +00:00
unsigned char buf [ 76 ] ;
2007-12-26 11:34:17 +00:00
struct timeval to ;
2009-06-03 00:28:44 +00:00
long save_flags , flags ;
2009-01-29 15:10:19 +00:00
2007-12-26 11:34:17 +00:00
status = sanei_udp_open_broadcast ( & fd ) ;
if ( status ! = SANE_STATUS_GOOD )
return ;
2009-06-01 14:18:52 +00:00
sanei_udp_write_broadcast ( fd , 3289 , ( unsigned char * ) query , 15 ) ;
2008-01-09 17:10:08 +00:00
2007-12-26 11:34:17 +00:00
DBG ( 5 , " %s, sent discovery packet \n " , __func__ ) ;
to . tv_sec = 1 ;
to . tv_usec = 0 ;
FD_ZERO ( & rfds ) ;
FD_SET ( fd , & rfds ) ;
2009-06-03 00:28:44 +00:00
save_flags = flags = fcntl ( fd , F_GETFL , 0L ) ;
flags | = O_NONBLOCK ;
fcntl ( fd , F_SETFL , flags ) ;
2007-12-26 11:34:17 +00:00
if ( select ( fd + 1 , & rfds , NULL , NULL , & to ) > 0 ) {
2008-01-09 17:10:08 +00:00
while ( ( len = sanei_udp_recvfrom ( fd , buf , 76 , & ip ) ) = = 76 ) {
2007-12-26 11:34:17 +00:00
DBG ( 5 , " response from %s \n " , ip ) ;
/* minimal check, protocol unknown */
2008-01-09 17:10:08 +00:00
if ( strncmp ( ( char * ) buf , " EPSON " , 5 ) = = 0 )
2007-12-26 11:34:17 +00:00
attach_one_net ( ip ) ;
}
}
2009-06-03 00:28:44 +00:00
fcntl ( fd , F_SETFL , save_flags ) ;
2007-12-26 11:34:17 +00:00
DBG ( 5 , " %s, end \n " , __func__ ) ;
sanei_udp_close ( fd ) ;
}
2006-12-02 14:47:21 +00:00
/*
2006-12-18 00:13:09 +00:00
* open_scanner ( )
*
* Open the scanner device . Depending on the connection method ,
* different open functions are called .
2006-12-02 14:47:21 +00:00
*/
static SANE_Status
2009-06-03 00:28:44 +00:00
open_scanner ( Epson_Scanner * s )
2006-12-02 14:47:21 +00:00
{
2006-12-18 00:13:09 +00:00
SANE_Status status = 0 ;
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
DBG ( 7 , " %s: %s \n " , __func__ , s - > hw - > sane . name ) ;
2006-12-02 14:47:21 +00:00
2006-12-18 00:13:09 +00:00
if ( s - > fd ! = - 1 ) {
DBG ( 5 , " scanner is already open: fd = %d \n " , s - > fd ) ;
return SANE_STATUS_GOOD ; /* no need to open the scanner */
2006-12-02 14:47:21 +00:00
}
2006-12-18 00:13:09 +00:00
if ( s - > hw - > connection = = SANE_EPSON_NET ) {
unsigned char buf [ 5 ] ;
2006-12-02 14:47:21 +00:00
2008-01-09 17:10:08 +00:00
/* Sleep a bit or the network scanner will not be ready */
2009-06-03 16:52:59 +00:00
sleep ( 2 ) ;
2008-01-09 17:10:08 +00:00
2006-12-18 00:13:09 +00:00
status = sanei_tcp_open ( s - > hw - > sane . name , 1865 , & s - > fd ) ;
2009-06-03 16:52:59 +00:00
if ( status = = SANE_STATUS_GOOD ) {
2009-06-16 14:24:43 +00:00
ssize_t read ;
struct timeval tv ;
tv . tv_sec = 5 ;
tv . tv_usec = 0 ;
setsockopt ( s - > fd , SOL_SOCKET , SO_RCVTIMEO , ( char * ) & tv , sizeof ( tv ) ) ;
2009-06-03 16:52:59 +00:00
s - > netlen = 0 ;
2006-12-02 14:47:21 +00:00
2009-06-16 14:24:43 +00:00
DBG ( 32 , " awaiting welcome message \n " ) ;
2009-06-03 16:52:59 +00:00
/* the scanner sends a kind of welcome msg */
2009-06-16 14:24:43 +00:00
read = e2_recv ( s , buf , 5 , & status ) ;
if ( read ! = 5 )
return SANE_STATUS_IO_ERROR ;
DBG ( 32 , " welcome message received, locking the scanner... \n " ) ;
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
/* lock the scanner for use by sane */
sanei_epson_net_lock ( s ) ;
2009-06-16 14:24:43 +00:00
DBG ( 32 , " scanner locked \n " ) ;
2009-06-03 16:52:59 +00:00
}
2008-01-09 17:10:08 +00:00
} else if ( s - > hw - > connection = = SANE_EPSON_SCSI )
2006-12-18 00:13:09 +00:00
status = sanei_scsi_open ( s - > hw - > sane . name , & s - > fd ,
sanei_epson2_scsi_sense_handler ,
NULL ) ;
else if ( s - > hw - > connection = = SANE_EPSON_PIO )
status = sanei_pio_open ( s - > hw - > sane . name , & s - > fd ) ;
else if ( s - > hw - > connection = = SANE_EPSON_USB )
status = sanei_usb_open ( s - > hw - > sane . name , & s - > fd ) ;
2006-12-02 14:47:21 +00:00
2006-12-18 00:13:09 +00:00
if ( status ! = SANE_STATUS_GOOD )
DBG ( 1 , " %s open failed: %s \n " , s - > hw - > sane . name ,
sane_strstatus ( status ) ) ;
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
if ( status = = SANE_STATUS_ACCESS_DENIED ) {
DBG ( 1 , " please check that you have permissions on the device. \n " ) ;
DBG ( 1 , " if this is a multi-function device with a printer, \n " ) ;
DBG ( 1 , " disable any conflicting driver (like usblp). \n " ) ;
}
2009-06-16 14:24:43 +00:00
DBG ( 5 , " scanner opened \n " ) ;
2006-12-02 14:47:21 +00:00
return status ;
}
2009-06-03 16:52:59 +00:00
static SANE_Status detect_scsi ( struct Epson_Scanner * s )
{
SANE_Status status ;
struct Epson_Device * dev = s - > hw ;
char buf [ INQUIRY_BUF_SIZE + 1 ] ;
size_t buf_size = INQUIRY_BUF_SIZE ;
char * vendor = buf + 8 ;
char * model = buf + 16 ;
char * rev = buf + 32 ;
status = sanei_epson2_scsi_inquiry ( s - > fd , buf , & buf_size ) ;
if ( status ! = SANE_STATUS_GOOD ) {
DBG ( 1 , " %s: inquiry failed: %s \n " , __func__ ,
sane_strstatus ( status ) ) ;
return status ;
}
buf [ INQUIRY_BUF_SIZE ] = 0 ;
DBG ( 1 , " inquiry data: \n " ) ;
DBG ( 1 , " vendor : %.8s \n " , vendor ) ;
DBG ( 1 , " model : %.16s \n " , model ) ;
DBG ( 1 , " revision: %.4s \n " , rev ) ;
if ( buf [ 0 ] ! = TYPE_PROCESSOR ) {
DBG ( 1 , " %s: device is not of processor type (%d) \n " ,
__func__ , buf [ 0 ] ) ;
return SANE_STATUS_INVAL ;
}
if ( strncmp ( vendor , " EPSON " , 5 ) ! = 0 ) {
DBG ( 1 ,
" %s: device doesn't look like an EPSON scanner \n " ,
__func__ ) ;
return SANE_STATUS_INVAL ;
}
if ( strncmp ( model , " SCANNER " , 8 ) ! = 0
& & strncmp ( model , " FilmScan 200 " , 12 ) ! = 0
& & strncmp ( model , " Perfection " , 10 ) ! = 0
& & strncmp ( model , " Expression " , 10 ) ! = 0
& & strncmp ( model , " GT " , 2 ) ! = 0 ) {
DBG ( 1 , " %s: this EPSON scanner is not supported \n " ,
__func__ ) ;
return SANE_STATUS_INVAL ;
}
if ( strncmp ( model , " FilmScan 200 " , 12 ) = = 0 ) {
dev - > sane . type = " film scanner " ;
e2_set_model ( s , ( unsigned char * ) model , 12 ) ;
}
/* Issue a test unit ready SCSI command. The FilmScan 200
* requires it for a sort of " wake up " . We might eventually
* get the return code and reissue it in case of failure .
*/
sanei_epson2_scsi_test_unit_ready ( s - > fd ) ;
return SANE_STATUS_GOOD ;
}
static SANE_Status
detect_usb ( struct Epson_Scanner * s )
{
SANE_Status status ;
int vendor , product ;
int i , numIds ;
SANE_Bool is_valid ;
/* if the sanei_usb_get_vendor_product call is not supported,
* then we just ignore this and rely on the user to config
* the correct device .
*/
status = sanei_usb_get_vendor_product ( s - > fd , & vendor , & product ) ;
if ( status ! = SANE_STATUS_GOOD ) {
DBG ( 1 ,
" cannot use IOCTL interface to verify that device is a scanner - will continue \n " ) ;
return SANE_STATUS_GOOD ;
}
/* check the vendor ID to see if we are dealing with an EPSON device */
if ( vendor ! = SANE_EPSON_VENDOR_ID ) {
/* this is not a supported vendor ID */
DBG ( 1 ,
" the device at %s is not manufactured by EPSON (vendor id=0x%x) \n " ,
s - > hw - > sane . name , vendor ) ;
return SANE_STATUS_INVAL ;
}
numIds = sanei_epson_getNumberOfUSBProductIds ( ) ;
is_valid = SANE_FALSE ;
i = 0 ;
/* check all known product IDs to verify that we know
about the device */
while ( i ! = numIds & & ! is_valid ) {
if ( product = = sanei_epson_usb_product_ids [ i ] )
is_valid = SANE_TRUE ;
i + + ;
}
if ( is_valid = = SANE_FALSE ) {
DBG ( 1 ,
" the device at %s is not a supported EPSON scanner (product id=0x%x) \n " ,
s - > hw - > sane . name , product ) ;
return SANE_STATUS_INVAL ;
}
DBG ( 1 ,
" found valid EPSON scanner: 0x%x/0x%x (vendorID/productID) \n " ,
vendor , product ) ;
return SANE_STATUS_GOOD ;
}
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
static int num_devices ; /* number of scanners attached to backend */
static Epson_Device * first_dev ; /* first EPSON scanner in list */
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* attach device to backend */
2006-12-18 00:13:09 +00:00
static SANE_Status
2009-06-03 00:28:44 +00:00
attach ( const char * name , Epson_Device * * devp , int type )
2006-12-02 14:47:21 +00:00
{
2009-06-01 14:18:52 +00:00
SANE_Status status ;
Epson_Scanner * s ;
struct Epson_Device * dev ;
int port ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
DBG ( 7 , " %s: devname = %s, type = %d \n " , __func__ , name , type ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
for ( dev = first_dev ; dev ; dev = dev - > next ) {
if ( strcmp ( dev - > sane . name , name ) = = 0 ) {
if ( devp ) {
* devp = dev ;
}
return SANE_STATUS_GOOD ;
}
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* alloc and clear our device structure */
dev = malloc ( sizeof ( * dev ) ) ;
if ( ! dev ) {
DBG ( 1 , " out of memory (line %d) \n " , __LINE__ ) ;
return SANE_STATUS_NO_MEM ;
}
memset ( dev , 0x00 , sizeof ( struct Epson_Device ) ) ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
/* check for PIO devices */
/* can we convert the device name to an integer? This is only possible
with PIO devices */
if ( type ! = SANE_EPSON_NET ) {
port = atoi ( name ) ;
if ( port ! = 0 )
type = SANE_EPSON_PIO ;
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( strncmp
( name , SANE_EPSON_CONFIG_PIO ,
strlen ( SANE_EPSON_CONFIG_PIO ) ) = = 0 ) {
/* we have a match for the PIO string and adjust the device name */
name + = strlen ( SANE_EPSON_CONFIG_PIO ) ;
name = sanei_config_skip_whitespace ( name ) ;
type = SANE_EPSON_PIO ;
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s = malloc ( sizeof ( struct Epson_Scanner ) ) ;
if ( s = = NULL )
2006-12-18 00:13:09 +00:00
return SANE_STATUS_NO_MEM ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
memset ( s , 0x00 , sizeof ( struct Epson_Scanner ) ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > fd = - 1 ;
s - > hw = dev ;
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
e2_dev_init ( dev , name , type ) ;
2008-01-09 17:10:08 +00:00
2009-06-03 16:52:59 +00:00
status = open_scanner ( s ) ;
if ( status ! = SANE_STATUS_GOOD ) {
free ( s ) ;
return status ;
2009-06-01 14:18:52 +00:00
}
2008-01-09 17:10:08 +00:00
2009-06-03 16:52:59 +00:00
/* from now on, close_scanner() must be called */
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
/* SCSI and USB requires special care */
if ( dev - > connection = = SANE_EPSON_SCSI ) {
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
status = detect_scsi ( s ) ;
2006-12-12 01:12:07 +00:00
2009-06-03 16:52:59 +00:00
} else if ( dev - > connection = = SANE_EPSON_USB ) {
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
status = detect_usb ( s ) ;
}
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
if ( status ! = SANE_STATUS_GOOD ) {
close_scanner ( s ) ;
free ( s ) ;
return status ;
2008-01-09 17:10:08 +00:00
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* set name and model (if not already set) */
if ( dev - > model = = NULL )
e2_set_model ( s , ( unsigned char * ) " generic " , 7 ) ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
dev - > name = strdup ( name ) ;
dev - > sane . name = dev - > name ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* ESC @, reset */
2009-06-03 16:52:59 +00:00
status = esci_reset ( s ) ;
if ( status ! = SANE_STATUS_GOOD )
goto free ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
status = e2_discover_capabilities ( s ) ;
if ( status ! = SANE_STATUS_GOOD )
goto free ;
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
if ( source_list [ 0 ] = = NULL | | dev - > dpi_range . min = = 0 ) {
DBG ( 1 , " something is wrong in the discovery process, aborting. \n " ) ;
status = SANE_STATUS_IO_ERROR ;
goto free ;
}
2009-06-01 14:18:52 +00:00
/* If we have been unable to obtain supported resolutions
* due to the fact we are on the network transport ,
* add some convenient ones
*/
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( dev - > res_list_size = = 0 & & dev - > connection = = SANE_EPSON_NET ) {
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
int val = ( dev - > dpi_range . min < 150 ) ? 150 : dev - > dpi_range . min ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
DBG ( 1 , " networked scanner, faking resolution list (%d-%d) \n " ,
2009-06-03 00:28:44 +00:00
dev - > dpi_range . min , dev - > dpi_range . max ) ;
2006-12-02 14:47:21 +00:00
2009-06-03 00:28:44 +00:00
if ( dev - > dpi_range . min < = 50 )
e2_add_resolution ( s , 50 ) ;
2007-12-26 11:34:17 +00:00
2009-06-03 00:28:44 +00:00
if ( dev - > dpi_range . min < = 75 )
e2_add_resolution ( s , 75 ) ;
2006-12-02 14:47:21 +00:00
2009-06-03 00:28:44 +00:00
if ( dev - > dpi_range . min < = 100 )
e2_add_resolution ( s , 100 ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
while ( val < = dev - > dpi_range . max ) {
e2_add_resolution ( s , val ) ;
val * = 2 ;
}
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/*
* Copy the resolution list to the resolution_list array so that the frontend can
* display the correct values
*/
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
dev - > resolution_list =
malloc ( ( dev - > res_list_size + 1 ) * sizeof ( SANE_Word ) ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( dev - > resolution_list = = NULL ) {
status = SANE_STATUS_NO_MEM ;
goto free ;
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
* ( dev - > resolution_list ) = dev - > res_list_size ;
memcpy ( & ( dev - > resolution_list [ 1 ] ) , dev - > res_list ,
dev - > res_list_size * sizeof ( SANE_Word ) ) ;
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
status = esci_reset ( s ) ;
if ( status ! = SANE_STATUS_GOOD )
goto free ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
DBG ( 1 , " scanner model: %s \n " , dev - > model ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* establish defaults */
dev - > need_reset_on_source_change = SANE_FALSE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( e2_model ( s , " ES-9000H " ) | | e2_model ( s , " GT-30000 " ) ) {
dev - > cmd - > set_focus_position = 0 ;
dev - > cmd - > feed = 0x19 ;
2006-12-02 14:47:21 +00:00
}
2009-06-01 14:18:52 +00:00
if ( e2_model ( s , " GT-8200 " ) | | e2_model ( s , " Perfection1650 " )
| | e2_model ( s , " Perfection1640 " ) | | e2_model ( s , " GT-8700 " ) ) {
dev - > cmd - > feed = 0 ;
dev - > cmd - > set_focus_position = 0 ;
dev - > need_reset_on_source_change = SANE_TRUE ;
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* we are done with this one, prepare for the next scanner */
2009-06-03 16:52:59 +00:00
2009-06-01 14:18:52 +00:00
num_devices + + ;
dev - > next = first_dev ;
first_dev = dev ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( devp )
* devp = dev ;
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
free :
2009-06-01 14:18:52 +00:00
close_scanner ( s ) ;
free ( s ) ;
return status ;
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/*
* Part of the SANE API : Attaches the scanner with the device name in * dev .
*/
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
static SANE_Status
2009-06-03 16:52:59 +00:00
attach_one_scsi ( const char * dev )
2009-06-01 14:18:52 +00:00
{
DBG ( 7 , " %s: dev = %s \n " , __func__ , dev ) ;
return attach ( dev , 0 , SANE_EPSON_SCSI ) ;
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
SANE_Status
attach_one_usb ( const char * dev )
{
DBG ( 7 , " %s: dev = %s \n " , __func__ , dev ) ;
return attach ( dev , 0 , SANE_EPSON_USB ) ;
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
static SANE_Status
attach_one_net ( const char * dev )
{
DBG ( 7 , " %s: dev = %s \n " , __func__ , dev ) ;
return attach ( dev , 0 , SANE_EPSON_NET ) ;
}
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
static SANE_Status
attach_one_config ( SANEI_Config __sane_unused__ * config , const char * line )
2009-06-01 14:18:52 +00:00
{
2009-06-03 16:52:59 +00:00
int vendor , product ;
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
int len = strlen ( line ) ;
2008-01-09 17:10:08 +00:00
2009-06-03 16:52:59 +00:00
DBG ( 7 , " %s: len = %d, line = %s \n " , __func__ , len , line ) ;
if ( sscanf ( line , " usb %i %i " , & vendor , & product ) = = 2 ) {
/* add the vendor and product IDs to the list of
known devices before we call the attach function */
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
int numIds = sanei_epson_getNumberOfUSBProductIds ( ) ;
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
if ( vendor ! = 0x4b8 )
return SANE_STATUS_INVAL ; /* this is not an EPSON device */
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
sanei_epson_usb_product_ids [ numIds - 1 ] = product ;
sanei_usb_attach_matching_devices ( line , attach_one_usb ) ;
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
} else if ( strncmp ( line , " usb " , 3 ) = = 0 & & len = = 3 ) {
int i , numIds ;
numIds = sanei_epson_getNumberOfUSBProductIds ( ) ;
for ( i = 0 ; i < numIds ; i + + ) {
sanei_usb_find_devices ( 0x4b8 ,
sanei_epson_usb_product_ids [ i ] , attach_one_usb ) ;
2008-01-09 17:10:08 +00:00
}
2006-12-18 00:13:09 +00:00
2009-06-03 16:52:59 +00:00
} else if ( strncmp ( line , " net " , 3 ) = = 0 ) {
/* remove the "net" sub string */
const char * name = sanei_config_skip_whitespace ( line + 3 ) ;
if ( strncmp ( name , " autodiscovery " , 13 ) = = 0 )
e2_network_discovery ( ) ;
else
attach_one_net ( name ) ;
} else {
sanei_config_attach_matching_devices ( line , attach_one_scsi ) ;
}
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
return SANE_STATUS_GOOD ;
}
2006-12-18 00:13:09 +00:00
2009-06-03 16:52:59 +00:00
static void
free_devices ( void )
2009-06-01 14:18:52 +00:00
{
Epson_Device * dev , * next ;
2006-12-18 00:13:09 +00:00
2009-06-03 16:52:59 +00:00
DBG ( 5 , " %s \n " , __func__ ) ;
2009-06-01 14:18:52 +00:00
for ( dev = first_dev ; dev ; dev = next ) {
next = dev - > next ;
free ( dev - > name ) ;
free ( dev - > model ) ;
free ( dev ) ;
2008-01-09 17:10:08 +00:00
}
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
free ( devlist ) ;
2009-06-03 16:52:59 +00:00
first_dev = NULL ;
}
static void
probe_devices ( void )
{
DBG ( 5 , " %s \n " , __func__ ) ;
free_devices ( ) ;
sanei_configure_attach ( EPSON2_CONFIG_FILE , NULL ,
attach_one_config ) ;
}
SANE_Status
sane_init ( SANE_Int * version_code , SANE_Auth_Callback __sane_unused__ authorize )
{
DBG_INIT ( ) ;
DBG ( 2 , " %s: " PACKAGE " " VERSION " \n " , __func__ ) ;
DBG ( 1 , " epson2 backend, version %i.%i.%i \n " ,
EPSON2_VERSION , EPSON2_REVISION , EPSON2_BUILD ) ;
if ( version_code ! = NULL )
* version_code = SANE_VERSION_CODE ( SANE_CURRENT_MAJOR , V_MINOR ,
EPSON2_BUILD ) ;
sanei_usb_init ( ) ;
return SANE_STATUS_GOOD ;
}
/* Clean up the list of attached scanners. */
void
sane_exit ( void )
{
DBG ( 5 , " %s \n " , __func__ ) ;
free_devices ( ) ;
2009-06-01 14:18:52 +00:00
}
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
SANE_Status
2009-06-03 16:52:59 +00:00
sane_get_devices ( const SANE_Device * * * device_list , SANE_Bool __sane_unused__ local_only )
2009-06-01 14:18:52 +00:00
{
Epson_Device * dev ;
int i ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
DBG ( 5 , " %s \n " , __func__ ) ;
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
probe_devices ( ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
devlist = malloc ( ( num_devices + 1 ) * sizeof ( devlist [ 0 ] ) ) ;
if ( ! devlist ) {
DBG ( 1 , " out of memory (line %d) \n " , __LINE__ ) ;
return SANE_STATUS_NO_MEM ;
2006-12-02 14:47:21 +00:00
}
2009-06-03 16:52:59 +00:00
DBG ( 5 , " %s - results: \n " , __func__ ) ;
2009-06-01 14:18:52 +00:00
for ( i = 0 , dev = first_dev ; i < num_devices ; dev = dev - > next , i + + ) {
2009-06-03 16:52:59 +00:00
DBG ( 1 , " %d (%d): %s \n " , i , dev - > connection , dev - > model ) ;
2009-06-01 14:18:52 +00:00
devlist [ i ] = & dev - > sane ;
2008-01-09 17:10:08 +00:00
}
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
devlist [ i ] = NULL ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
* device_list = devlist ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
return SANE_STATUS_GOOD ;
2008-01-09 17:10:08 +00:00
}
2006-12-18 00:13:09 +00:00
2008-01-09 17:10:08 +00:00
static SANE_Status
2009-06-03 00:28:44 +00:00
init_options ( Epson_Scanner * s )
2008-01-09 17:10:08 +00:00
{
2009-06-01 14:18:52 +00:00
int i ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
for ( i = 0 ; i < NUM_OPTIONS ; + + i ) {
s - > opt [ i ] . size = sizeof ( SANE_Word ) ;
s - > opt [ i ] . cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT ;
2008-01-09 17:10:08 +00:00
}
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
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 ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
/* "Scan Mode" group: */
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_MODE_GROUP ] . title = SANE_I18N ( " Scan Mode " ) ;
s - > opt [ OPT_MODE_GROUP ] . desc = " " ;
s - > opt [ OPT_MODE_GROUP ] . type = SANE_TYPE_GROUP ;
s - > opt [ OPT_MODE_GROUP ] . cap = 0 ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
/* scan mode */
s - > opt [ OPT_MODE ] . name = SANE_NAME_SCAN_MODE ;
s - > opt [ OPT_MODE ] . title = SANE_TITLE_SCAN_MODE ;
s - > opt [ OPT_MODE ] . desc = SANE_DESC_SCAN_MODE ;
s - > opt [ OPT_MODE ] . type = SANE_TYPE_STRING ;
s - > opt [ OPT_MODE ] . size = max_string_size ( mode_list ) ;
s - > opt [ OPT_MODE ] . constraint_type = SANE_CONSTRAINT_STRING_LIST ;
s - > opt [ OPT_MODE ] . constraint . string_list = mode_list ;
s - > val [ OPT_MODE ] . w = 0 ; /* Binary */
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
/* bit depth */
s - > opt [ OPT_BIT_DEPTH ] . name = SANE_NAME_BIT_DEPTH ;
s - > opt [ OPT_BIT_DEPTH ] . title = SANE_TITLE_BIT_DEPTH ;
s - > opt [ OPT_BIT_DEPTH ] . desc = SANE_DESC_BIT_DEPTH ;
s - > opt [ OPT_BIT_DEPTH ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_BIT_DEPTH ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_BIT_DEPTH ] . constraint_type = SANE_CONSTRAINT_WORD_LIST ;
s - > opt [ OPT_BIT_DEPTH ] . constraint . word_list = s - > hw - > depth_list ;
s - > opt [ OPT_BIT_DEPTH ] . cap | = SANE_CAP_INACTIVE ;
s - > val [ OPT_BIT_DEPTH ] . w = s - > hw - > depth_list [ 1 ] ; /* the first "real" element is the default */
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
if ( s - > hw - > depth_list [ 0 ] = = 1 ) /* only one element in the list -> hide the option */
s - > opt [ OPT_BIT_DEPTH ] . cap | = SANE_CAP_INACTIVE ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
/* halftone */
s - > opt [ OPT_HALFTONE ] . name = SANE_NAME_HALFTONE ;
s - > opt [ OPT_HALFTONE ] . title = SANE_TITLE_HALFTONE ;
2009-06-15 22:38:24 +00:00
s - > opt [ OPT_HALFTONE ] . desc = SANE_I18N ( " Selects the halftone " ) ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_HALFTONE ] . type = SANE_TYPE_STRING ;
s - > opt [ OPT_HALFTONE ] . size = max_string_size ( halftone_list_7 ) ;
s - > opt [ OPT_HALFTONE ] . constraint_type = SANE_CONSTRAINT_STRING_LIST ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
/* XXX use defines */
if ( s - > hw - > level > = 7 )
s - > opt [ OPT_HALFTONE ] . constraint . string_list = halftone_list_7 ;
else if ( s - > hw - > level > = 4 )
s - > opt [ OPT_HALFTONE ] . constraint . string_list = halftone_list_4 ;
else
s - > opt [ OPT_HALFTONE ] . constraint . string_list = halftone_list ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
s - > val [ OPT_HALFTONE ] . w = 1 ; /* Halftone A */
2006-12-18 00:13:09 +00:00
2009-06-03 00:28:44 +00:00
if ( ! s - > hw - > cmd - > set_halftoning )
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_HALFTONE ] . cap | = SANE_CAP_INACTIVE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* dropout */
s - > opt [ OPT_DROPOUT ] . name = " dropout " ;
s - > opt [ OPT_DROPOUT ] . title = SANE_I18N ( " Dropout " ) ;
2009-06-15 22:38:24 +00:00
s - > opt [ OPT_DROPOUT ] . desc = SANE_I18N ( " Selects the dropout " ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_DROPOUT ] . type = SANE_TYPE_STRING ;
s - > opt [ OPT_DROPOUT ] . size = max_string_size ( dropout_list ) ;
s - > opt [ OPT_DROPOUT ] . cap | = SANE_CAP_ADVANCED ;
s - > opt [ OPT_DROPOUT ] . constraint_type = SANE_CONSTRAINT_STRING_LIST ;
s - > opt [ OPT_DROPOUT ] . constraint . string_list = dropout_list ;
s - > val [ OPT_DROPOUT ] . w = 0 ; /* None */
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* brightness */
s - > opt [ OPT_BRIGHTNESS ] . name = SANE_NAME_BRIGHTNESS ;
s - > opt [ OPT_BRIGHTNESS ] . title = SANE_TITLE_BRIGHTNESS ;
2009-06-15 22:38:24 +00:00
s - > opt [ OPT_BRIGHTNESS ] . desc = SANE_I18N ( " Selects the brightness " ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_BRIGHTNESS ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_BRIGHTNESS ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_BRIGHTNESS ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_BRIGHTNESS ] . constraint . range = & s - > hw - > cmd - > bright_range ;
s - > val [ OPT_BRIGHTNESS ] . w = 0 ; /* Normal */
2006-12-18 00:13:09 +00:00
2009-06-03 00:28:44 +00:00
if ( ! s - > hw - > cmd - > set_bright )
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_BRIGHTNESS ] . cap | = SANE_CAP_INACTIVE ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
/* sharpness */
s - > opt [ OPT_SHARPNESS ] . name = " sharpness " ;
s - > opt [ OPT_SHARPNESS ] . title = SANE_I18N ( " Sharpness " ) ;
s - > opt [ OPT_SHARPNESS ] . desc = " " ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_SHARPNESS ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_SHARPNESS ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_SHARPNESS ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_SHARPNESS ] . constraint . range = & outline_emphasis_range ;
s - > val [ OPT_SHARPNESS ] . w = 0 ; /* Normal */
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( ! s - > hw - > cmd - > set_outline_emphasis )
s - > opt [ OPT_SHARPNESS ] . cap | = SANE_CAP_INACTIVE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* gamma */
2009-06-15 22:38:24 +00:00
s - > opt [ OPT_GAMMA_CORRECTION ] . name = " gamma-correction " ;
s - > opt [ OPT_GAMMA_CORRECTION ] . title = SANE_I18N ( " Gamma Correction " ) ;
s - > opt [ OPT_GAMMA_CORRECTION ] . desc = SANE_I18N ( " Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scanner " ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_GAMMA_CORRECTION ] . type = SANE_TYPE_STRING ;
s - > opt [ OPT_GAMMA_CORRECTION ] . constraint_type =
SANE_CONSTRAINT_STRING_LIST ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/*
* special handling for D1 function level - at this time I ' m not
* testing for D1 , I ' m just assuming that all D level scanners will
* behave the same way . This has to be confirmed with the next D - level
* scanner
*/
if ( s - > hw - > cmd - > level [ 0 ] = = ' D ' ) {
s - > opt [ OPT_GAMMA_CORRECTION ] . size =
max_string_size ( gamma_list_d ) ;
s - > opt [ OPT_GAMMA_CORRECTION ] . constraint . string_list =
gamma_list_d ;
s - > val [ OPT_GAMMA_CORRECTION ] . w = 1 ; /* Default */
gamma_userdefined = gamma_userdefined_d ;
gamma_params = gamma_params_d ;
} else {
s - > opt [ OPT_GAMMA_CORRECTION ] . size =
max_string_size ( gamma_list_ab ) ;
s - > opt [ OPT_GAMMA_CORRECTION ] . constraint . string_list =
gamma_list_ab ;
s - > val [ OPT_GAMMA_CORRECTION ] . w = 0 ; /* Default */
gamma_userdefined = gamma_userdefined_ab ;
gamma_params = gamma_params_ab ;
}
2007-11-18 09:36:04 +00:00
2009-06-03 00:28:44 +00:00
if ( ! s - > hw - > cmd - > set_gamma )
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_GAMMA_CORRECTION ] . cap | = SANE_CAP_INACTIVE ;
2007-11-18 09:36:04 +00:00
2009-06-01 14:18:52 +00:00
/* gamma vector */
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/*
s - > opt [ OPT_GAMMA_VECTOR ] . name = SANE_NAME_GAMMA_VECTOR ;
s - > opt [ OPT_GAMMA_VECTOR ] . title = SANE_TITLE_GAMMA_VECTOR ;
s - > opt [ OPT_GAMMA_VECTOR ] . desc = SANE_DESC_GAMMA_VECTOR ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_GAMMA_VECTOR ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_GAMMA_VECTOR ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_GAMMA_VECTOR ] . size = 256 * sizeof ( SANE_Word ) ;
s - > opt [ OPT_GAMMA_VECTOR ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_GAMMA_VECTOR ] . constraint . range = & u8_range ;
s - > val [ OPT_GAMMA_VECTOR ] . wa = & s - > gamma_table [ 0 ] [ 0 ] ;
*/
2008-01-09 17:10:08 +00:00
2009-06-01 14:18:52 +00:00
/* red gamma vector */
s - > opt [ OPT_GAMMA_VECTOR_R ] . name = SANE_NAME_GAMMA_VECTOR_R ;
s - > opt [ OPT_GAMMA_VECTOR_R ] . title = SANE_TITLE_GAMMA_VECTOR_R ;
s - > opt [ OPT_GAMMA_VECTOR_R ] . desc = SANE_DESC_GAMMA_VECTOR_R ;
2006-12-12 01:12:07 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_GAMMA_VECTOR_R ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_GAMMA_VECTOR_R ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_GAMMA_VECTOR_R ] . size = 256 * sizeof ( SANE_Word ) ;
s - > opt [ OPT_GAMMA_VECTOR_R ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_GAMMA_VECTOR_R ] . constraint . range = & u8_range ;
s - > val [ OPT_GAMMA_VECTOR_R ] . wa = & s - > gamma_table [ 0 ] [ 0 ] ;
2008-01-09 17:10:08 +00:00
2009-06-01 14:18:52 +00:00
/* green gamma vector */
s - > opt [ OPT_GAMMA_VECTOR_G ] . name = SANE_NAME_GAMMA_VECTOR_G ;
s - > opt [ OPT_GAMMA_VECTOR_G ] . title = SANE_TITLE_GAMMA_VECTOR_G ;
s - > opt [ OPT_GAMMA_VECTOR_G ] . desc = SANE_DESC_GAMMA_VECTOR_G ;
2008-01-09 17:10:08 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_GAMMA_VECTOR_G ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_GAMMA_VECTOR_G ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_GAMMA_VECTOR_G ] . size = 256 * sizeof ( SANE_Word ) ;
s - > opt [ OPT_GAMMA_VECTOR_G ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_GAMMA_VECTOR_G ] . constraint . range = & u8_range ;
s - > val [ OPT_GAMMA_VECTOR_G ] . wa = & s - > gamma_table [ 1 ] [ 0 ] ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* red gamma vector */
s - > opt [ OPT_GAMMA_VECTOR_B ] . name = SANE_NAME_GAMMA_VECTOR_B ;
s - > opt [ OPT_GAMMA_VECTOR_B ] . title = SANE_TITLE_GAMMA_VECTOR_B ;
s - > opt [ OPT_GAMMA_VECTOR_B ] . desc = SANE_DESC_GAMMA_VECTOR_B ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_GAMMA_VECTOR_B ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_GAMMA_VECTOR_B ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_GAMMA_VECTOR_B ] . size = 256 * sizeof ( SANE_Word ) ;
s - > opt [ OPT_GAMMA_VECTOR_B ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_GAMMA_VECTOR_B ] . constraint . range = & u8_range ;
s - > val [ OPT_GAMMA_VECTOR_B ] . wa = & s - > gamma_table [ 2 ] [ 0 ] ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( s - > hw - > cmd - > set_gamma_table
& & gamma_userdefined [ s - > val [ OPT_GAMMA_CORRECTION ] . w ] = =
SANE_TRUE ) {
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* s->opt[ OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; */
s - > opt [ OPT_GAMMA_VECTOR_R ] . cap & = ~ SANE_CAP_INACTIVE ;
s - > opt [ OPT_GAMMA_VECTOR_G ] . cap & = ~ SANE_CAP_INACTIVE ;
s - > opt [ OPT_GAMMA_VECTOR_B ] . cap & = ~ SANE_CAP_INACTIVE ;
} else {
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* s->opt[ OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; */
s - > opt [ OPT_GAMMA_VECTOR_R ] . cap | = SANE_CAP_INACTIVE ;
s - > opt [ OPT_GAMMA_VECTOR_G ] . cap | = SANE_CAP_INACTIVE ;
s - > opt [ OPT_GAMMA_VECTOR_B ] . cap | = SANE_CAP_INACTIVE ;
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* initialize the Gamma tables */
memset ( & s - > gamma_table [ 0 ] , 0 , 256 * sizeof ( SANE_Word ) ) ;
memset ( & s - > gamma_table [ 1 ] , 0 , 256 * sizeof ( SANE_Word ) ) ;
memset ( & s - > gamma_table [ 2 ] , 0 , 256 * sizeof ( SANE_Word ) ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* memset(&s->gamma_table[3], 0, 256 * sizeof(SANE_Word)); */
for ( i = 0 ; i < 256 ; i + + ) {
s - > gamma_table [ 0 ] [ i ] = i ;
s - > gamma_table [ 1 ] [ i ] = i ;
s - > gamma_table [ 2 ] [ i ] = i ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* s->gamma_table[3][i] = i; */
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* color correction */
s - > opt [ OPT_COLOR_CORRECTION ] . name = " color-correction " ;
s - > opt [ OPT_COLOR_CORRECTION ] . title = SANE_I18N ( " Color correction " ) ;
s - > opt [ OPT_COLOR_CORRECTION ] . desc =
SANE_I18N
2009-06-15 22:38:24 +00:00
( " Sets the color correction table for the selected output device " ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_COLOR_CORRECTION ] . type = SANE_TYPE_STRING ;
s - > opt [ OPT_COLOR_CORRECTION ] . size = 32 ;
s - > opt [ OPT_COLOR_CORRECTION ] . cap | = SANE_CAP_ADVANCED ;
s - > opt [ OPT_COLOR_CORRECTION ] . constraint_type =
SANE_CONSTRAINT_STRING_LIST ;
s - > opt [ OPT_COLOR_CORRECTION ] . constraint . string_list = color_list ;
s - > val [ OPT_COLOR_CORRECTION ] . w = 5 ; /* scanner default: CRT monitors */
2008-01-09 17:10:08 +00:00
2009-06-03 00:28:44 +00:00
if ( ! s - > hw - > cmd - > set_color_correction )
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_COLOR_CORRECTION ] . cap | = SANE_CAP_INACTIVE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* resolution */
s - > opt [ OPT_RESOLUTION ] . name = SANE_NAME_SCAN_RESOLUTION ;
s - > opt [ OPT_RESOLUTION ] . title = SANE_TITLE_SCAN_RESOLUTION ;
s - > opt [ OPT_RESOLUTION ] . desc = SANE_DESC_SCAN_RESOLUTION ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_RESOLUTION ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_RESOLUTION ] . unit = SANE_UNIT_DPI ;
s - > opt [ OPT_RESOLUTION ] . constraint_type = SANE_CONSTRAINT_WORD_LIST ;
s - > opt [ OPT_RESOLUTION ] . constraint . word_list = s - > hw - > resolution_list ;
s - > val [ OPT_RESOLUTION ] . w = s - > hw - > dpi_range . min ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* threshold */
s - > opt [ OPT_THRESHOLD ] . name = SANE_NAME_THRESHOLD ;
s - > opt [ OPT_THRESHOLD ] . title = SANE_TITLE_THRESHOLD ;
s - > opt [ OPT_THRESHOLD ] . desc = SANE_DESC_THRESHOLD ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_THRESHOLD ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_THRESHOLD ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_THRESHOLD ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_THRESHOLD ] . constraint . range = & u8_range ;
s - > val [ OPT_THRESHOLD ] . w = 0x80 ;
2006-12-02 14:47:21 +00:00
2009-06-03 00:28:44 +00:00
if ( ! s - > hw - > cmd - > set_threshold )
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_THRESHOLD ] . cap | = SANE_CAP_INACTIVE ;
2008-01-09 17:10:08 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_CCT_GROUP ] . title =
SANE_I18N ( " Color correction coefficients " ) ;
s - > opt [ OPT_CCT_GROUP ] . desc =
SANE_I18N ( " Matrix multiplication of RGB " ) ;
s - > opt [ OPT_CCT_GROUP ] . type = SANE_TYPE_GROUP ;
s - > opt [ OPT_CCT_GROUP ] . cap = SANE_CAP_ADVANCED ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* color correction coefficients */
s - > opt [ OPT_CCT_1 ] . name = " cct-1 " ;
s - > opt [ OPT_CCT_2 ] . name = " cct-2 " ;
s - > opt [ OPT_CCT_3 ] . name = " cct-3 " ;
s - > opt [ OPT_CCT_4 ] . name = " cct-4 " ;
s - > opt [ OPT_CCT_5 ] . name = " cct-5 " ;
s - > opt [ OPT_CCT_6 ] . name = " cct-6 " ;
s - > opt [ OPT_CCT_7 ] . name = " cct-7 " ;
s - > opt [ OPT_CCT_8 ] . name = " cct-8 " ;
s - > opt [ OPT_CCT_9 ] . name = " cct-9 " ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_CCT_1 ] . title = SANE_I18N ( " Green " ) ;
s - > opt [ OPT_CCT_2 ] . title = SANE_I18N ( " Shift green to red " ) ;
s - > opt [ OPT_CCT_3 ] . title = SANE_I18N ( " Shift green to blue " ) ;
s - > opt [ OPT_CCT_4 ] . title = SANE_I18N ( " Shift red to green " ) ;
s - > opt [ OPT_CCT_5 ] . title = SANE_I18N ( " Red " ) ;
s - > opt [ OPT_CCT_6 ] . title = SANE_I18N ( " Shift red to blue " ) ;
s - > opt [ OPT_CCT_7 ] . title = SANE_I18N ( " Shift blue to green " ) ;
s - > opt [ OPT_CCT_8 ] . title = SANE_I18N ( " Shift blue to red " ) ;
s - > opt [ OPT_CCT_9 ] . title = SANE_I18N ( " Blue " ) ;
2009-01-15 19:18:05 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_CCT_1 ] . desc = SANE_I18N ( " Controls green level " ) ;
s - > opt [ OPT_CCT_2 ] . desc =
SANE_I18N ( " Adds to red based on green level " ) ;
s - > opt [ OPT_CCT_3 ] . desc =
SANE_I18N ( " Adds to blue based on green level " ) ;
s - > opt [ OPT_CCT_4 ] . desc =
SANE_I18N ( " Adds to green based on red level " ) ;
s - > opt [ OPT_CCT_5 ] . desc = SANE_I18N ( " Controls red level " ) ;
s - > opt [ OPT_CCT_6 ] . desc = SANE_I18N ( " Adds to blue based on red level " ) ;
s - > opt [ OPT_CCT_7 ] . desc =
SANE_I18N ( " Adds to green based on blue level " ) ;
s - > opt [ OPT_CCT_8 ] . desc = SANE_I18N ( " Adds to red based on blue level " ) ;
s - > opt [ OPT_CCT_9 ] . desc = SANE_I18N ( " Controls blue level " ) ;
2009-01-15 19:18:05 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_CCT_1 ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_CCT_2 ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_CCT_3 ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_CCT_4 ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_CCT_5 ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_CCT_6 ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_CCT_7 ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_CCT_8 ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_CCT_9 ] . type = SANE_TYPE_INT ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_CCT_1 ] . cap | = SANE_CAP_ADVANCED | SANE_CAP_INACTIVE ;
s - > opt [ OPT_CCT_2 ] . cap | = SANE_CAP_ADVANCED | SANE_CAP_INACTIVE ;
s - > opt [ OPT_CCT_3 ] . cap | = SANE_CAP_ADVANCED | SANE_CAP_INACTIVE ;
s - > opt [ OPT_CCT_4 ] . cap | = SANE_CAP_ADVANCED | SANE_CAP_INACTIVE ;
s - > opt [ OPT_CCT_5 ] . cap | = SANE_CAP_ADVANCED | SANE_CAP_INACTIVE ;
s - > opt [ OPT_CCT_6 ] . cap | = SANE_CAP_ADVANCED | SANE_CAP_INACTIVE ;
s - > opt [ OPT_CCT_7 ] . cap | = SANE_CAP_ADVANCED | SANE_CAP_INACTIVE ;
s - > opt [ OPT_CCT_8 ] . cap | = SANE_CAP_ADVANCED | SANE_CAP_INACTIVE ;
s - > opt [ OPT_CCT_9 ] . cap | = SANE_CAP_ADVANCED | SANE_CAP_INACTIVE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_CCT_1 ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_CCT_2 ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_CCT_3 ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_CCT_4 ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_CCT_5 ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_CCT_6 ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_CCT_7 ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_CCT_8 ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_CCT_9 ] . unit = SANE_UNIT_NONE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_CCT_1 ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_CCT_2 ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_CCT_3 ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_CCT_4 ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_CCT_5 ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_CCT_6 ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_CCT_7 ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_CCT_8 ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_CCT_9 ] . constraint_type = SANE_CONSTRAINT_RANGE ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_CCT_1 ] . constraint . range = & s8_range ;
s - > opt [ OPT_CCT_2 ] . constraint . range = & s8_range ;
s - > opt [ OPT_CCT_3 ] . constraint . range = & s8_range ;
s - > opt [ OPT_CCT_4 ] . constraint . range = & s8_range ;
s - > opt [ OPT_CCT_5 ] . constraint . range = & s8_range ;
s - > opt [ OPT_CCT_6 ] . constraint . range = & s8_range ;
s - > opt [ OPT_CCT_7 ] . constraint . range = & s8_range ;
s - > opt [ OPT_CCT_8 ] . constraint . range = & s8_range ;
s - > opt [ OPT_CCT_9 ] . constraint . range = & s8_range ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > val [ OPT_CCT_1 ] . w = 32 ;
s - > val [ OPT_CCT_2 ] . w = 0 ;
s - > val [ OPT_CCT_3 ] . w = 0 ;
s - > val [ OPT_CCT_4 ] . w = 0 ;
s - > val [ OPT_CCT_5 ] . w = 32 ;
s - > val [ OPT_CCT_6 ] . w = 0 ;
s - > val [ OPT_CCT_7 ] . w = 0 ;
s - > val [ OPT_CCT_8 ] . w = 0 ;
s - > val [ OPT_CCT_9 ] . w = 32 ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* "Advanced" group: */
s - > opt [ OPT_ADVANCED_GROUP ] . title = SANE_I18N ( " Advanced " ) ;
s - > opt [ OPT_ADVANCED_GROUP ] . desc = " " ;
s - > opt [ OPT_ADVANCED_GROUP ] . type = SANE_TYPE_GROUP ;
s - > opt [ OPT_ADVANCED_GROUP ] . cap = SANE_CAP_ADVANCED ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* mirror */
s - > opt [ OPT_MIRROR ] . name = " mirror " ;
s - > opt [ OPT_MIRROR ] . title = SANE_I18N ( " Mirror image " ) ;
2009-06-15 22:38:24 +00:00
s - > opt [ OPT_MIRROR ] . desc = SANE_I18N ( " Mirror the image " ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_MIRROR ] . type = SANE_TYPE_BOOL ;
s - > val [ OPT_MIRROR ] . w = SANE_FALSE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( ! s - > hw - > cmd - > mirror_image )
s - > opt [ OPT_MIRROR ] . cap | = SANE_CAP_INACTIVE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* auto area segmentation */
s - > opt [ OPT_AAS ] . name = " auto-area-segmentation " ;
s - > opt [ OPT_AAS ] . title = SANE_I18N ( " Auto area segmentation " ) ;
s - > opt [ OPT_AAS ] . desc =
" Enables different dithering modes in image and text areas " ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_AAS ] . type = SANE_TYPE_BOOL ;
s - > val [ OPT_AAS ] . w = SANE_TRUE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( ! s - > hw - > cmd - > control_auto_area_segmentation )
s - > opt [ OPT_AAS ] . cap | = SANE_CAP_INACTIVE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* limit resolution list */
s - > opt [ OPT_LIMIT_RESOLUTION ] . name = " short-resolution " ;
s - > opt [ OPT_LIMIT_RESOLUTION ] . title =
SANE_I18N ( " Short resolution list " ) ;
s - > opt [ OPT_LIMIT_RESOLUTION ] . desc =
SANE_I18N ( " Display a shortened resolution list " ) ;
s - > opt [ OPT_LIMIT_RESOLUTION ] . type = SANE_TYPE_BOOL ;
s - > val [ OPT_LIMIT_RESOLUTION ] . w = SANE_FALSE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* "Preview settings" group: */
s - > opt [ OPT_PREVIEW_GROUP ] . title = SANE_TITLE_PREVIEW ;
s - > opt [ OPT_PREVIEW_GROUP ] . desc = " " ;
s - > opt [ OPT_PREVIEW_GROUP ] . type = SANE_TYPE_GROUP ;
s - > opt [ OPT_PREVIEW_GROUP ] . cap = SANE_CAP_ADVANCED ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* preview */
s - > opt [ OPT_PREVIEW ] . name = SANE_NAME_PREVIEW ;
s - > opt [ OPT_PREVIEW ] . title = SANE_TITLE_PREVIEW ;
s - > opt [ OPT_PREVIEW ] . desc = SANE_DESC_PREVIEW ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_PREVIEW ] . type = SANE_TYPE_BOOL ;
s - > val [ OPT_PREVIEW ] . w = SANE_FALSE ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
/* "Geometry" group: */
s - > opt [ OPT_GEOMETRY_GROUP ] . title = SANE_I18N ( " Geometry " ) ;
s - > opt [ OPT_GEOMETRY_GROUP ] . desc = " " ;
s - > opt [ OPT_GEOMETRY_GROUP ] . type = SANE_TYPE_GROUP ;
s - > opt [ OPT_GEOMETRY_GROUP ] . cap = SANE_CAP_ADVANCED ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* top-left x */
s - > opt [ OPT_TL_X ] . name = SANE_NAME_SCAN_TL_X ;
s - > opt [ OPT_TL_X ] . title = SANE_TITLE_SCAN_TL_X ;
s - > opt [ OPT_TL_X ] . desc = SANE_DESC_SCAN_TL_X ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_TL_X ] . type = SANE_TYPE_FIXED ;
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 - > hw - > x_range ;
s - > val [ OPT_TL_X ] . w = 0 ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* top-left y */
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 ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_TL_Y ] . type = SANE_TYPE_FIXED ;
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 - > hw - > y_range ;
s - > val [ OPT_TL_Y ] . w = 0 ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* bottom-right x */
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 ;
2007-11-18 09:36:04 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_BR_X ] . type = SANE_TYPE_FIXED ;
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 - > hw - > x_range ;
s - > val [ OPT_BR_X ] . w = s - > hw - > x_range - > max ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* bottom-right y */
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 ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_BR_Y ] . type = SANE_TYPE_FIXED ;
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 - > hw - > y_range ;
s - > val [ OPT_BR_Y ] . w = s - > hw - > y_range - > max ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* "Optional equipment" group: */
s - > opt [ OPT_EQU_GROUP ] . title = SANE_I18N ( " Optional equipment " ) ;
s - > opt [ OPT_EQU_GROUP ] . desc = " " ;
s - > opt [ OPT_EQU_GROUP ] . type = SANE_TYPE_GROUP ;
s - > opt [ OPT_EQU_GROUP ] . cap = SANE_CAP_ADVANCED ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* source */
s - > opt [ OPT_SOURCE ] . name = SANE_NAME_SCAN_SOURCE ;
s - > opt [ OPT_SOURCE ] . title = SANE_TITLE_SCAN_SOURCE ;
s - > opt [ OPT_SOURCE ] . desc = SANE_DESC_SCAN_SOURCE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_SOURCE ] . type = SANE_TYPE_STRING ;
s - > opt [ OPT_SOURCE ] . size = max_string_size ( source_list ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_SOURCE ] . constraint_type = SANE_CONSTRAINT_STRING_LIST ;
s - > opt [ OPT_SOURCE ] . constraint . string_list = source_list ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( ! s - > hw - > extension )
s - > opt [ OPT_SOURCE ] . cap | = SANE_CAP_INACTIVE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > val [ OPT_SOURCE ] . w = 0 ; /* always use Flatbed as default */
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* film type */
s - > opt [ OPT_FILM_TYPE ] . name = " film-type " ;
s - > opt [ OPT_FILM_TYPE ] . title = SANE_I18N ( " Film type " ) ;
s - > opt [ OPT_FILM_TYPE ] . desc = " " ;
s - > opt [ OPT_FILM_TYPE ] . type = SANE_TYPE_STRING ;
s - > opt [ OPT_FILM_TYPE ] . size = max_string_size ( film_list ) ;
s - > opt [ OPT_FILM_TYPE ] . constraint_type = SANE_CONSTRAINT_STRING_LIST ;
s - > opt [ OPT_FILM_TYPE ] . constraint . string_list = film_list ;
s - > val [ OPT_FILM_TYPE ] . w = 0 ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( ! s - > hw - > cmd - > set_bay )
s - > opt [ OPT_FILM_TYPE ] . cap | = SANE_CAP_INACTIVE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* focus position */
2009-06-15 22:38:24 +00:00
s - > opt [ OPT_FOCUS ] . name = " focus-position " ;
s - > opt [ OPT_FOCUS ] . title = SANE_I18N ( " Focus Position " ) ;
s - > opt [ OPT_FOCUS ] . desc = SANE_I18N ( " Sets the focus position to either the glass or 2.5mm above the glass " ) ;
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_FOCUS ] . type = SANE_TYPE_STRING ;
s - > opt [ OPT_FOCUS ] . size = max_string_size ( focus_list ) ;
s - > opt [ OPT_FOCUS ] . constraint_type = SANE_CONSTRAINT_STRING_LIST ;
s - > opt [ OPT_FOCUS ] . constraint . string_list = focus_list ;
s - > val [ OPT_FOCUS ] . w = 0 ;
s - > opt [ OPT_FOCUS ] . cap | = SANE_CAP_ADVANCED ;
2009-06-03 00:28:44 +00:00
if ( s - > hw - > focusSupport = = SANE_TRUE )
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_FOCUS ] . cap & = ~ SANE_CAP_INACTIVE ;
2009-06-03 00:28:44 +00:00
else
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_FOCUS ] . cap | = SANE_CAP_INACTIVE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* forward feed / eject */
s - > opt [ OPT_EJECT ] . name = " eject " ;
s - > opt [ OPT_EJECT ] . title = SANE_I18N ( " Eject " ) ;
s - > opt [ OPT_EJECT ] . desc = SANE_I18N ( " Eject the sheet in the ADF " ) ;
s - > opt [ OPT_EJECT ] . type = SANE_TYPE_BUTTON ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( ( ! s - > hw - > ADF ) & & ( ! s - > hw - > cmd - > set_bay ) ) { /* Hack: Using set_bay to indicate. */
s - > opt [ OPT_EJECT ] . cap | = SANE_CAP_INACTIVE ;
2006-12-02 14:47:21 +00:00
}
2009-06-01 14:18:52 +00:00
/* auto forward feed / eject */
s - > opt [ OPT_AUTO_EJECT ] . name = " auto-eject " ;
s - > opt [ OPT_AUTO_EJECT ] . title = SANE_I18N ( " Auto eject " ) ;
s - > opt [ OPT_AUTO_EJECT ] . desc =
SANE_I18N ( " Eject document after scanning " ) ;
s - > opt [ OPT_AUTO_EJECT ] . type = SANE_TYPE_BOOL ;
s - > val [ OPT_AUTO_EJECT ] . w = SANE_FALSE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( ! s - > hw - > ADF )
s - > opt [ OPT_AUTO_EJECT ] . cap | = SANE_CAP_INACTIVE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_ADF_MODE ] . name = " adf-mode " ;
s - > opt [ OPT_ADF_MODE ] . title = SANE_I18N ( " ADF Mode " ) ;
s - > opt [ OPT_ADF_MODE ] . desc =
SANE_I18N ( " Selects the ADF mode (simplex/duplex) " ) ;
s - > opt [ OPT_ADF_MODE ] . type = SANE_TYPE_STRING ;
s - > opt [ OPT_ADF_MODE ] . size = max_string_size ( adf_mode_list ) ;
s - > opt [ OPT_ADF_MODE ] . constraint_type = SANE_CONSTRAINT_STRING_LIST ;
s - > opt [ OPT_ADF_MODE ] . constraint . string_list = adf_mode_list ;
s - > val [ OPT_ADF_MODE ] . w = 0 ; /* simplex */
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( ( ! s - > hw - > ADF ) | | ( s - > hw - > duplex = = SANE_FALSE ) )
s - > opt [ OPT_ADF_MODE ] . cap | = SANE_CAP_INACTIVE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* select bay */
s - > opt [ OPT_BAY ] . name = " bay " ;
s - > opt [ OPT_BAY ] . title = SANE_I18N ( " Bay " ) ;
s - > opt [ OPT_BAY ] . desc = SANE_I18N ( " Select bay to scan " ) ;
s - > opt [ OPT_BAY ] . type = SANE_TYPE_STRING ;
s - > opt [ OPT_BAY ] . size = max_string_size ( bay_list ) ;
s - > opt [ OPT_BAY ] . constraint_type = SANE_CONSTRAINT_STRING_LIST ;
s - > opt [ OPT_BAY ] . constraint . string_list = bay_list ;
s - > val [ OPT_BAY ] . w = 0 ; /* Bay 1 */
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( ! s - > hw - > cmd - > set_bay )
s - > opt [ OPT_BAY ] . cap | = SANE_CAP_INACTIVE ;
2006-12-02 14:47:21 +00:00
2009-06-15 22:38:24 +00:00
s - > opt [ OPT_WAIT_FOR_BUTTON ] . name = " wait-for-button " ;
s - > opt [ OPT_WAIT_FOR_BUTTON ] . title = SANE_I18N ( " Wait for button " ) ;
s - > opt [ OPT_WAIT_FOR_BUTTON ] . desc = SANE_I18N ( " After sending the scan command, wait until the button on the scanner is pressed " ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_WAIT_FOR_BUTTON ] . type = SANE_TYPE_BOOL ;
s - > opt [ OPT_WAIT_FOR_BUTTON ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_WAIT_FOR_BUTTON ] . constraint_type = SANE_CONSTRAINT_NONE ;
s - > opt [ OPT_WAIT_FOR_BUTTON ] . constraint . range = NULL ;
s - > opt [ OPT_WAIT_FOR_BUTTON ] . cap | = SANE_CAP_ADVANCED ;
2006-12-02 14:47:21 +00:00
2009-06-03 00:28:44 +00:00
if ( ! s - > hw - > cmd - > request_push_button_status )
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_WAIT_FOR_BUTTON ] . cap | = SANE_CAP_INACTIVE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
return SANE_STATUS_GOOD ;
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
SANE_Status
2009-06-03 00:28:44 +00:00
sane_open ( SANE_String_Const name , SANE_Handle * handle )
2009-06-01 14:18:52 +00:00
{
SANE_Status status ;
Epson_Device * dev ;
Epson_Scanner * s ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
DBG ( 7 , " %s: name = %s \n " , __func__ , name ) ;
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
/* do a scan if the devices list is empty */
if ( first_dev = = NULL )
probe_devices ( ) ;
2009-06-01 14:18:52 +00:00
/* search for device */
if ( name [ 0 ] ) {
for ( dev = first_dev ; dev ; dev = dev - > next )
if ( strcmp ( dev - > sane . name , name ) = = 0 )
break ;
} else
dev = first_dev ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
if ( ! dev ) {
DBG ( 1 , " error opening the device \n " ) ;
return SANE_STATUS_INVAL ;
2006-12-02 14:47:21 +00:00
}
2009-06-03 16:52:59 +00:00
s = malloc ( sizeof ( Epson_Scanner ) ) ;
2009-06-01 14:18:52 +00:00
if ( ! s ) {
DBG ( 1 , " out of memory (line %d) \n " , __LINE__ ) ;
return SANE_STATUS_NO_MEM ;
2006-12-02 14:47:21 +00:00
}
2009-06-03 16:52:59 +00:00
memset ( s , 0x00 , sizeof ( struct Epson_Scanner ) ) ;
2009-06-01 14:18:52 +00:00
s - > fd = - 1 ;
s - > hw = dev ;
init_options ( s ) ;
* handle = ( SANE_Handle ) s ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
status = open_scanner ( s ) ;
if ( status ! = SANE_STATUS_GOOD )
return status ;
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
status = esci_reset ( s ) ;
if ( status ! = SANE_STATUS_GOOD )
return status ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
return status ;
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
void
sane_close ( SANE_Handle handle )
{
int i ;
2009-06-03 16:52:59 +00:00
Epson_Scanner * s ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/*
* XXX Test if there is still data pending from
* the scanner . If so , then do a cancel
*/
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s = ( Epson_Scanner * ) handle ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
if ( s - > fd ! = - 1 )
close_scanner ( s ) ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
for ( i = 0 ; i < LINES_SHUFFLE_MAX ; i + + ) {
if ( s - > line_buffer [ i ] ! = NULL )
free ( s - > line_buffer [ i ] ) ;
2006-12-18 00:13:09 +00:00
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
free ( s ) ;
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
const SANE_Option_Descriptor *
sane_get_option_descriptor ( SANE_Handle handle , SANE_Int option )
{
Epson_Scanner * s = ( Epson_Scanner * ) handle ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
if ( option < 0 | | option > = NUM_OPTIONS )
return NULL ;
2006-12-02 14:47:21 +00:00
2009-06-03 00:28:44 +00:00
return s - > opt + option ;
2009-06-01 14:18:52 +00:00
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
static const SANE_String_Const *
2009-06-03 00:28:44 +00:00
search_string_list ( const SANE_String_Const * list , SANE_String value )
2009-06-01 14:18:52 +00:00
{
2009-06-03 00:28:44 +00:00
while ( * list ! = NULL & & strcmp ( value , * list ) ! = 0 )
list + + ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
return ( ( * list = = NULL ) ? NULL : list ) ;
2006-12-02 14:47:21 +00:00
}
/*
2009-06-01 14:18:52 +00:00
Activate , deactivate an option . Subroutines so we can add
debugging info if we want . The change flag is set to TRUE
if we changed an option . If we did not change an option ,
then the value of the changed flag is not modified .
*/
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
static void
2009-06-03 00:28:44 +00:00
activateOption ( Epson_Scanner * s , SANE_Int option , SANE_Bool * change )
2006-12-02 14:47:21 +00:00
{
2009-06-01 14:18:52 +00:00
if ( ! SANE_OPTION_IS_ACTIVE ( s - > opt [ option ] . cap ) ) {
s - > opt [ option ] . cap & = ~ SANE_CAP_INACTIVE ;
* change = SANE_TRUE ;
}
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
static void
2009-06-03 00:28:44 +00:00
deactivateOption ( Epson_Scanner * s , SANE_Int option , SANE_Bool * change )
2009-06-01 14:18:52 +00:00
{
if ( SANE_OPTION_IS_ACTIVE ( s - > opt [ option ] . cap ) ) {
s - > opt [ option ] . cap | = SANE_CAP_INACTIVE ;
* change = SANE_TRUE ;
}
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
static void
2009-06-03 00:28:44 +00:00
setOptionState ( Epson_Scanner * s , SANE_Bool state , SANE_Int option ,
SANE_Bool * change )
2009-06-01 14:18:52 +00:00
{
if ( state )
activateOption ( s , option , change ) ;
else
deactivateOption ( s , option , change ) ;
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
static SANE_Status
getvalue ( SANE_Handle handle , SANE_Int option , void * value )
{
Epson_Scanner * s = ( Epson_Scanner * ) handle ;
SANE_Option_Descriptor * sopt = & ( s - > opt [ option ] ) ;
Option_Value * sval = & ( s - > val [ option ] ) ;
2006-12-02 14:47:21 +00:00
2009-06-03 16:52:59 +00:00
DBG ( 17 , " %s: option = %d \n " , __func__ , option ) ;
2009-06-01 14:18:52 +00:00
switch ( option ) {
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* case OPT_GAMMA_VECTOR: */
case OPT_GAMMA_VECTOR_R :
case OPT_GAMMA_VECTOR_G :
case OPT_GAMMA_VECTOR_B :
memcpy ( value , sval - > wa , sopt - > size ) ;
break ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
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_MIRROR :
case OPT_AAS :
case OPT_PREVIEW :
case OPT_BRIGHTNESS :
case OPT_SHARPNESS :
case OPT_AUTO_EJECT :
case OPT_CCT_1 :
case OPT_CCT_2 :
case OPT_CCT_3 :
case OPT_CCT_4 :
case OPT_CCT_5 :
case OPT_CCT_6 :
case OPT_CCT_7 :
case OPT_CCT_8 :
case OPT_CCT_9 :
case OPT_THRESHOLD :
case OPT_BIT_DEPTH :
case OPT_WAIT_FOR_BUTTON :
case OPT_LIMIT_RESOLUTION :
* ( ( SANE_Word * ) value ) = sval - > w ;
break ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
case OPT_MODE :
case OPT_ADF_MODE :
case OPT_HALFTONE :
case OPT_DROPOUT :
case OPT_SOURCE :
case OPT_FILM_TYPE :
case OPT_GAMMA_CORRECTION :
case OPT_COLOR_CORRECTION :
case OPT_BAY :
case OPT_FOCUS :
strcpy ( ( char * ) value , sopt - > constraint . string_list [ sval - > w ] ) ;
break ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
default :
return SANE_STATUS_INVAL ;
2006-12-02 14:47:21 +00:00
}
2009-06-01 14:18:52 +00:00
return SANE_STATUS_GOOD ;
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/*
* This routine handles common options between OPT_MODE and
* OPT_HALFTONE . These options are TET ( a HALFTONE mode ) , AAS
* - auto area segmentation , and threshold . Apparently AAS
* is some method to differentiate between text and photos .
* Or something like that .
*
* AAS is available when the scan color depth is 1 and the
* halftone method is not TET .
*
* Threshold is available when halftone is NONE , and depth is 1.
*/
static void
2009-06-03 00:28:44 +00:00
handle_depth_halftone ( Epson_Scanner * s , SANE_Bool * reload )
2009-06-01 14:18:52 +00:00
{
int hti = s - > val [ OPT_HALFTONE ] . w ;
int mdi = s - > val [ OPT_MODE ] . w ;
SANE_Bool aas = SANE_FALSE ;
SANE_Bool thresh = SANE_FALSE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( ! s - > hw - > cmd - > control_auto_area_segmentation )
return ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( mode_params [ mdi ] . depth = = 1 ) {
if ( halftone_params [ hti ] ! = HALFTONE_TET )
aas = SANE_TRUE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( halftone_params [ hti ] = = HALFTONE_NONE )
thresh = SANE_TRUE ;
2006-12-02 14:47:21 +00:00
}
2009-06-01 14:18:52 +00:00
setOptionState ( s , aas , OPT_AAS , reload ) ;
setOptionState ( s , thresh , OPT_THRESHOLD , reload ) ;
}
/*
* Handles setting the source ( flatbed , transparency adapter ( TPU ) ,
* or auto document feeder ( ADF ) ) .
*
* For newer scanners it also sets the focus according to the
* glass / TPU settings .
*/
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
static void
2009-06-03 00:28:44 +00:00
change_source ( Epson_Scanner * s , SANE_Int optindex , char * value )
2009-06-01 14:18:52 +00:00
{
int force_max = SANE_FALSE ;
SANE_Bool dummy ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
DBG ( 1 , " %s: optindex = %d, source = '%s' \n " , __func__ , optindex ,
value ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* reset the scanner when we are changing the source setting -
this is necessary for the Perfection 1650 */
if ( s - > hw - > need_reset_on_source_change )
esci_reset ( s ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > focusOnGlass = SANE_TRUE ; /* this is the default */
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( s - > val [ OPT_SOURCE ] . w = = optindex )
return ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > val [ OPT_SOURCE ] . w = optindex ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( s - > val [ OPT_TL_X ] . w = = s - > hw - > x_range - > min
& & s - > val [ OPT_TL_Y ] . w = = s - > hw - > y_range - > min
& & s - > val [ OPT_BR_X ] . w = = s - > hw - > x_range - > max
& & s - > val [ OPT_BR_Y ] . w = = s - > hw - > y_range - > max ) {
force_max = SANE_TRUE ;
2006-12-02 14:47:21 +00:00
}
2009-06-01 14:18:52 +00:00
if ( strcmp ( ADF_STR , value ) = = 0 ) {
s - > hw - > x_range = & s - > hw - > adf_x_range ;
s - > hw - > y_range = & s - > hw - > adf_y_range ;
s - > hw - > use_extension = SANE_TRUE ;
/* disable film type option */
deactivateOption ( s , OPT_FILM_TYPE , & dummy ) ;
s - > val [ OPT_FOCUS ] . w = 0 ;
if ( s - > hw - > duplex ) {
activateOption ( s , OPT_ADF_MODE , & dummy ) ;
} else {
deactivateOption ( s , OPT_ADF_MODE , & dummy ) ;
s - > val [ OPT_ADF_MODE ] . w = 0 ;
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
DBG ( 1 , " adf activated (%d %d) \n " , s - > hw - > use_extension ,
s - > hw - > duplex ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
} else if ( strcmp ( TPU_STR , value ) = = 0 ) {
s - > hw - > x_range = & s - > hw - > tpu_x_range ;
s - > hw - > y_range = & s - > hw - > tpu_y_range ;
s - > hw - > use_extension = SANE_TRUE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* enable film type option only if the scanner supports it */
if ( s - > hw - > cmd - > set_film_type ! = 0 )
activateOption ( s , OPT_FILM_TYPE , & dummy ) ;
else
deactivateOption ( s , OPT_FILM_TYPE , & dummy ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* enable focus position if the scanner supports it */
if ( s - > hw - > cmd - > set_focus_position ! = 0 ) {
s - > val [ OPT_FOCUS ] . w = 1 ;
s - > focusOnGlass = SANE_FALSE ;
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
deactivateOption ( s , OPT_ADF_MODE , & dummy ) ;
deactivateOption ( s , OPT_EJECT , & dummy ) ;
deactivateOption ( s , OPT_AUTO_EJECT , & dummy ) ;
} else {
/* neither ADF nor TPU active */
s - > hw - > x_range = & s - > hw - > fbf_x_range ;
s - > hw - > y_range = & s - > hw - > fbf_y_range ;
s - > hw - > use_extension = SANE_FALSE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* disable film type option */
deactivateOption ( s , OPT_FILM_TYPE , & dummy ) ;
s - > val [ OPT_FOCUS ] . w = 0 ;
deactivateOption ( s , OPT_ADF_MODE , & dummy ) ;
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* special handling for FilmScan 200 */
if ( s - > hw - > cmd - > level [ 0 ] = = ' F ' )
activateOption ( s , OPT_FILM_TYPE , & dummy ) ;
2008-01-09 17:10:08 +00:00
2009-06-01 14:18:52 +00:00
s - > opt [ OPT_BR_X ] . constraint . range = s - > hw - > x_range ;
s - > opt [ OPT_BR_Y ] . constraint . range = s - > hw - > y_range ;
2008-01-09 17:10:08 +00:00
2009-06-01 14:18:52 +00:00
if ( s - > val [ OPT_TL_X ] . w < s - > hw - > x_range - > min | | force_max )
s - > val [ OPT_TL_X ] . w = s - > hw - > x_range - > min ;
2008-01-09 17:10:08 +00:00
2009-06-01 14:18:52 +00:00
if ( s - > val [ OPT_TL_Y ] . w < s - > hw - > y_range - > min | | force_max )
s - > val [ OPT_TL_Y ] . w = s - > hw - > y_range - > min ;
2008-01-09 17:10:08 +00:00
2009-06-01 14:18:52 +00:00
if ( s - > val [ OPT_BR_X ] . w > s - > hw - > x_range - > max | | force_max )
s - > val [ OPT_BR_X ] . w = s - > hw - > x_range - > max ;
2008-01-09 17:10:08 +00:00
2009-06-01 14:18:52 +00:00
if ( s - > val [ OPT_BR_Y ] . w > s - > hw - > y_range - > max | | force_max )
s - > val [ OPT_BR_Y ] . w = s - > hw - > y_range - > max ;
2008-01-09 17:10:08 +00:00
2009-06-01 14:18:52 +00:00
setOptionState ( s , s - > hw - > ADF
& & s - > hw - > use_extension , OPT_AUTO_EJECT , & dummy ) ;
setOptionState ( s , s - > hw - > ADF
& & s - > hw - > use_extension , OPT_EJECT , & dummy ) ;
2008-01-09 17:10:08 +00:00
}
2006-12-02 14:47:21 +00:00
static SANE_Status
2009-06-03 00:28:44 +00:00
setvalue ( SANE_Handle handle , SANE_Int option , void * value , SANE_Int * info )
2006-12-02 14:47:21 +00:00
{
2009-06-01 14:18:52 +00:00
Epson_Scanner * s = ( Epson_Scanner * ) handle ;
SANE_Option_Descriptor * sopt = & ( s - > opt [ option ] ) ;
Option_Value * sval = & ( s - > val [ option ] ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
SANE_Status status ;
const SANE_String_Const * optval ;
int optindex ;
SANE_Bool reload = SANE_FALSE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
DBG ( 17 , " %s: option = %d, value = %p \n " , __func__ , option , value ) ;
status = sanei_constrain_value ( sopt , value , info ) ;
if ( status ! = SANE_STATUS_GOOD )
return status ;
2008-01-09 17:10:08 +00:00
2009-06-01 14:18:52 +00:00
if ( info & & value & & ( * info & SANE_INFO_INEXACT )
& & sopt - > type = = SANE_TYPE_INT )
DBG ( 17 , " %s: constrained val = %d \n " , __func__ ,
* ( SANE_Word * ) value ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
s - > option_has_changed = SANE_TRUE ;
2008-12-26 22:02:32 +00:00
2009-06-01 14:18:52 +00:00
optval = NULL ;
optindex = 0 ;
2008-01-09 17:10:08 +00:00
2009-06-01 14:18:52 +00:00
if ( sopt - > constraint_type = = SANE_CONSTRAINT_STRING_LIST ) {
optval = search_string_list ( sopt - > constraint . string_list ,
( char * ) value ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( optval = = NULL )
return SANE_STATUS_INVAL ;
optindex = optval - sopt - > constraint . string_list ;
2006-12-02 14:47:21 +00:00
}
2009-06-01 14:18:52 +00:00
switch ( option ) {
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* case OPT_GAMMA_VECTOR: */
case OPT_GAMMA_VECTOR_R :
case OPT_GAMMA_VECTOR_G :
case OPT_GAMMA_VECTOR_B :
memcpy ( sval - > wa , value , sopt - > size ) ; /* Word arrays */
break ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
case OPT_CCT_1 :
case OPT_CCT_2 :
case OPT_CCT_3 :
case OPT_CCT_4 :
case OPT_CCT_5 :
case OPT_CCT_6 :
case OPT_CCT_7 :
case OPT_CCT_8 :
case OPT_CCT_9 :
sval - > w = * ( ( SANE_Word * ) value ) ; /* Simple values */
break ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
case OPT_DROPOUT :
case OPT_FILM_TYPE :
case OPT_BAY :
case OPT_FOCUS :
sval - > w = optindex ; /* Simple lists */
break ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
case OPT_EJECT :
/* XXX required? control_extension(s, 1); */
esci_eject ( s ) ;
break ;
case OPT_RESOLUTION :
sval - > w = * ( ( SANE_Word * ) value ) ;
DBG ( 17 , " setting resolution to %d \n " , sval - > w ) ;
reload = SANE_TRUE ;
break ;
case OPT_BR_X :
case OPT_BR_Y :
sval - > w = * ( ( SANE_Word * ) value ) ;
if ( SANE_UNFIX ( sval - > w ) = = 0 ) {
DBG ( 17 , " invalid br-x or br-y \n " ) ;
return SANE_STATUS_INVAL ;
}
/* passthru */
case OPT_TL_X :
case OPT_TL_Y :
sval - > w = * ( ( SANE_Word * ) value ) ;
DBG ( 17 , " setting size to %f \n " , SANE_UNFIX ( sval - > w ) ) ;
if ( NULL ! = info )
* info | = SANE_INFO_RELOAD_PARAMS ;
break ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
case OPT_SOURCE :
change_source ( s , optindex , ( char * ) value ) ;
reload = SANE_TRUE ;
break ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
case OPT_MODE :
{
SANE_Bool isColor = mode_params [ optindex ] . color ;
SANE_Bool userDefined =
color_userdefined [ s - > val [ OPT_COLOR_CORRECTION ] . w ] ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
sval - > w = optindex ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( s - > hw - > cmd - > set_halftoning ! = 0 )
setOptionState ( s ,
mode_params [ optindex ] . depth = =
1 , OPT_HALFTONE , & reload ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
setOptionState ( s , ! isColor , OPT_DROPOUT , & reload ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( s - > hw - > cmd - > set_color_correction )
setOptionState ( s , isColor ,
OPT_COLOR_CORRECTION , & reload ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( s - > hw - > cmd - > set_color_correction_coefficients ) {
setOptionState ( s , isColor
& & userDefined , OPT_CCT_1 , & reload ) ;
setOptionState ( s , isColor
& & userDefined , OPT_CCT_2 , & reload ) ;
setOptionState ( s , isColor
& & userDefined , OPT_CCT_3 , & reload ) ;
setOptionState ( s , isColor
& & userDefined , OPT_CCT_4 , & reload ) ;
setOptionState ( s , isColor
& & userDefined , OPT_CCT_5 , & reload ) ;
setOptionState ( s , isColor
& & userDefined , OPT_CCT_6 , & reload ) ;
setOptionState ( s , isColor
& & userDefined , OPT_CCT_7 , & reload ) ;
setOptionState ( s , isColor
& & userDefined , OPT_CCT_8 , & reload ) ;
setOptionState ( s , isColor
& & userDefined , OPT_CCT_9 , & reload ) ;
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* if binary, then disable the bit depth selection */
if ( optindex = = 0 ) {
s - > opt [ OPT_BIT_DEPTH ] . cap | = SANE_CAP_INACTIVE ;
} else {
if ( s - > hw - > depth_list [ 0 ] = = 1 )
s - > opt [ OPT_BIT_DEPTH ] . cap | =
SANE_CAP_INACTIVE ;
else {
s - > opt [ OPT_BIT_DEPTH ] . cap & =
~ SANE_CAP_INACTIVE ;
s - > val [ OPT_BIT_DEPTH ] . w =
mode_params [ optindex ] . depth ;
}
2006-12-02 14:47:21 +00:00
}
2009-06-01 14:18:52 +00:00
handle_depth_halftone ( s , & reload ) ;
reload = SANE_TRUE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
break ;
2006-12-02 14:47:21 +00:00
}
2009-06-01 14:18:52 +00:00
case OPT_ADF_MODE :
sval - > w = optindex ;
break ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
case OPT_BIT_DEPTH :
sval - > w = * ( ( SANE_Word * ) value ) ;
mode_params [ s - > val [ OPT_MODE ] . w ] . depth = sval - > w ;
reload = SANE_TRUE ;
break ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
case OPT_HALFTONE :
sval - > w = optindex ;
handle_depth_halftone ( s , & reload ) ;
break ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
case OPT_COLOR_CORRECTION :
{
SANE_Bool f = color_userdefined [ optindex ] ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
sval - > w = optindex ;
setOptionState ( s , f , OPT_CCT_1 , & reload ) ;
setOptionState ( s , f , OPT_CCT_2 , & reload ) ;
setOptionState ( s , f , OPT_CCT_3 , & reload ) ;
setOptionState ( s , f , OPT_CCT_4 , & reload ) ;
setOptionState ( s , f , OPT_CCT_5 , & reload ) ;
setOptionState ( s , f , OPT_CCT_6 , & reload ) ;
setOptionState ( s , f , OPT_CCT_7 , & reload ) ;
setOptionState ( s , f , OPT_CCT_8 , & reload ) ;
setOptionState ( s , f , OPT_CCT_9 , & reload ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
break ;
2006-12-02 14:47:21 +00:00
}
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
case OPT_GAMMA_CORRECTION :
{
SANE_Bool f = gamma_userdefined [ optindex ] ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
sval - > w = optindex ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
/* setOptionState(s, f, OPT_GAMMA_VECTOR, &reload ); */
setOptionState ( s , f , OPT_GAMMA_VECTOR_R , & reload ) ;
setOptionState ( s , f , OPT_GAMMA_VECTOR_G , & reload ) ;
setOptionState ( s , f , OPT_GAMMA_VECTOR_B , & reload ) ;
setOptionState ( s , ! f , OPT_BRIGHTNESS , & reload ) ; /* Note... */
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
break ;
}
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
case OPT_MIRROR :
case OPT_AAS :
case OPT_PREVIEW : /* needed? */
case OPT_BRIGHTNESS :
case OPT_SHARPNESS :
case OPT_AUTO_EJECT :
case OPT_THRESHOLD :
case OPT_WAIT_FOR_BUTTON :
sval - > w = * ( ( SANE_Word * ) value ) ;
break ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
case OPT_LIMIT_RESOLUTION :
sval - > w = * ( ( SANE_Word * ) value ) ;
filter_resolution_list ( s ) ;
reload = SANE_TRUE ;
break ;
2007-01-20 20:59:05 +00:00
2009-06-01 14:18:52 +00:00
default :
return SANE_STATUS_INVAL ;
}
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
if ( reload & & info ! = NULL )
* info | = SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
DBG ( 17 , " %s: end \n " , __func__ ) ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
return SANE_STATUS_GOOD ;
2006-12-18 00:13:09 +00:00
}
2009-06-01 14:18:52 +00:00
SANE_Status
sane_control_option ( SANE_Handle handle , SANE_Int option , SANE_Action action ,
2009-06-03 00:28:44 +00:00
void * value , SANE_Int * info )
2006-12-18 00:13:09 +00:00
{
2009-06-03 16:52:59 +00:00
DBG ( 17 , " %s: action = %x, option = %d \n " , __func__ , action , option ) ;
2009-06-01 14:18:52 +00:00
if ( option < 0 | | option > = NUM_OPTIONS )
return SANE_STATUS_INVAL ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
if ( info ! = NULL )
* info = 0 ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
switch ( action ) {
case SANE_ACTION_GET_VALUE :
return getvalue ( handle , option , value ) ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
case SANE_ACTION_SET_VALUE :
return setvalue ( handle , option , value , info ) ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
default :
return SANE_STATUS_INVAL ;
2008-01-09 17:10:08 +00:00
}
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
return SANE_STATUS_INVAL ;
2006-12-18 00:13:09 +00:00
}
2009-06-01 14:18:52 +00:00
SANE_Status
2009-06-03 00:28:44 +00:00
sane_get_parameters ( SANE_Handle handle , SANE_Parameters * params )
2006-12-18 00:13:09 +00:00
{
2009-06-01 14:18:52 +00:00
Epson_Scanner * s = ( Epson_Scanner * ) handle ;
int dpi , max_x , max_y ;
int bytes_per_pixel ;
2006-12-18 00:13:09 +00:00
2008-01-09 17:10:08 +00:00
DBG ( 5 , " %s \n " , __func__ ) ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
/*
* If sane_start was already called , then just retrieve the parameters
* from the scanner data structure
*/
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
if ( ! s - > eof & & s - > ptr ! = NULL ) {
DBG ( 5 , " returning saved params structure \n " ) ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
if ( params ! = NULL ) {
DBG ( 1 ,
" restoring parameters from saved parameters \n " ) ;
* params = s - > params ;
}
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
DBG ( 5 , " resolution = %d, preview = %d \n " ,
s - > val [ OPT_RESOLUTION ] . w , s - > val [ OPT_PREVIEW ] . w ) ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
DBG ( 5 , " get para tlx %f tly %f brx %f bry %f [mm] \n " ,
SANE_UNFIX ( s - > val [ OPT_TL_X ] . w ) ,
SANE_UNFIX ( s - > val [ OPT_TL_Y ] . w ) ,
SANE_UNFIX ( s - > val [ OPT_BR_X ] . w ) ,
SANE_UNFIX ( s - > val [ OPT_BR_Y ] . w ) ) ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
print_params ( s - > params ) ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
return SANE_STATUS_GOOD ;
2006-12-18 00:13:09 +00:00
}
2009-06-01 14:18:52 +00:00
/* otherwise initialize the params structure and gather the data */
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
memset ( & s - > params , 0 , sizeof ( SANE_Parameters ) ) ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
dpi = s - > val [ OPT_RESOLUTION ] . w ;
max_x = max_y = 0 ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
/* XXX check this */
s - > params . pixels_per_line =
( SANE_UNFIX ( s - > val [ OPT_BR_X ] . w -
s - > val [ OPT_TL_X ] . w ) / ( MM_PER_INCH * dpi ) ) + 0.5 ;
s - > params . lines =
( SANE_UNFIX ( s - > val [ OPT_BR_Y ] . w -
s - > val [ OPT_TL_Y ] . w ) / ( MM_PER_INCH * dpi ) ) + 0.5 ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
/*
* Make sure that the number of lines is correct for color shuffling :
* The shuffling alghorithm produces 2 xline_distance lines at the
* beginning and the same amount at the end of the scan that are not
* useable . If s - > params . lines gets negative , 0 lines are reported
* back to the frontend .
*/
if ( s - > hw - > color_shuffle ) {
s - > params . lines - = 4 * s - > line_distance ;
2009-06-03 00:28:44 +00:00
if ( s - > params . lines < 0 )
2009-06-01 14:18:52 +00:00
s - > params . lines = 0 ;
2009-06-03 00:28:44 +00:00
DBG ( 1 , " adjusted params.lines for color_shuffle by %d to %d \n " ,
2009-06-01 14:18:52 +00:00
4 * s - > line_distance , s - > params . lines ) ;
}
2008-11-18 20:26:55 +00:00
2009-06-01 14:18:52 +00:00
DBG ( 5 , " resolution = %d, preview = %d \n " ,
s - > val [ OPT_RESOLUTION ] . w , s - > val [ OPT_PREVIEW ] . w ) ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
DBG ( 5 , " get para %p %p tlx %f tly %f brx %f bry %f [mm] \n " ,
( void * ) s , ( void * ) s - > val , SANE_UNFIX ( s - > val [ OPT_TL_X ] . w ) ,
SANE_UNFIX ( s - > val [ OPT_TL_Y ] . w ) , SANE_UNFIX ( s - > val [ OPT_BR_X ] . w ) ,
SANE_UNFIX ( s - > val [ OPT_BR_Y ] . w ) ) ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
/*
* Calculate bytes_per_pixel and bytes_per_line for
* any color depths .
*
* The default color depth is stored in mode_params . depth :
*/
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
if ( mode_params [ s - > val [ OPT_MODE ] . w ] . depth = = 1 )
s - > params . depth = 1 ;
else
s - > params . depth = s - > val [ OPT_BIT_DEPTH ] . w ;
2008-01-09 17:10:08 +00:00
2009-06-01 14:18:52 +00:00
if ( s - > params . depth > 8 ) {
s - > params . depth = 16 ; /*
* The frontends can only handle 8 or 16 bits
* for gray or color - so if it ' s more than 8 ,
* it gets automatically set to 16. This works
* as long as EPSON does not come out with a
* scanner that can handle more than 16 bits
* per color channel .
*/
2006-12-18 00:13:09 +00:00
}
2009-06-01 14:18:52 +00:00
bytes_per_pixel = s - > params . depth / 8 ; /* this works because it can only be set to 1, 8 or 16 */
if ( s - > params . depth % 8 ) { /* just in case ... */
bytes_per_pixel + + ;
}
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
/* pixels_per_line is rounded to the next 8bit boundary */
s - > params . pixels_per_line = s - > params . pixels_per_line & ~ 7 ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
s - > params . last_frame = SANE_TRUE ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
if ( mode_params [ s - > val [ OPT_MODE ] . w ] . color ) {
s - > params . format = SANE_FRAME_RGB ;
s - > params . bytes_per_line =
3 * s - > params . pixels_per_line * bytes_per_pixel ;
} else {
s - > params . format = SANE_FRAME_GRAY ;
s - > params . bytes_per_line =
s - > params . pixels_per_line * s - > params . depth / 8 ;
2006-12-18 00:13:09 +00:00
}
2009-06-01 14:18:52 +00:00
if ( NULL ! = params )
* params = s - > params ;
print_params ( s - > params ) ;
2006-12-18 00:13:09 +00:00
2009-06-01 14:18:52 +00:00
return SANE_STATUS_GOOD ;
2006-12-18 00:13:09 +00:00
}
2006-12-02 14:47:21 +00:00
/*
* This function is part of the SANE API and gets called from the front end to
* start the scan process .
*/
SANE_Status
sane_start ( SANE_Handle handle )
{
Epson_Scanner * s = ( Epson_Scanner * ) handle ;
2006-12-18 00:13:09 +00:00
Epson_Device * dev = s - > hw ;
2006-12-02 14:47:21 +00:00
SANE_Status status ;
2006-12-07 19:28:02 +00:00
DBG ( 5 , " %s \n " , __func__ ) ;
2006-12-02 14:47:21 +00:00
2006-12-18 00:13:09 +00:00
/* check if we just have finished working with the ADF */
2008-01-09 17:10:08 +00:00
status = e2_check_adf ( s ) ;
2006-12-18 00:13:09 +00:00
if ( status ! = SANE_STATUS_GOOD )
return status ;
2006-12-02 14:47:21 +00:00
/* calc scanning parameters */
2008-12-26 22:02:32 +00:00
status = e2_init_parameters ( s ) ;
if ( status ! = SANE_STATUS_GOOD )
return status ;
2006-12-02 14:47:21 +00:00
/* ESC , bay */
if ( SANE_OPTION_IS_ACTIVE ( s - > opt [ OPT_BAY ] . cap ) ) {
2008-01-09 17:10:08 +00:00
status = esci_set_bay ( s , s - > val [ OPT_BAY ] . w ) ;
2006-12-02 14:47:21 +00:00
if ( status ! = SANE_STATUS_GOOD )
return status ;
}
/* set scanning parameters */
2009-06-03 00:28:44 +00:00
if ( dev - > extended_commands )
2008-01-09 17:10:08 +00:00
status = e2_set_extended_scanning_parameters ( s ) ;
2009-06-03 00:28:44 +00:00
else
2008-01-09 17:10:08 +00:00
status = e2_set_scanning_parameters ( s ) ;
2006-12-02 14:47:21 +00:00
if ( status ! = SANE_STATUS_GOOD )
return status ;
/* ESC z, user defined gamma table */
2006-12-18 00:13:09 +00:00
if ( dev - > cmd - > set_gamma_table
2006-12-02 14:47:21 +00:00
& & gamma_userdefined [ s - > val [ OPT_GAMMA_CORRECTION ] . w ] ) {
2008-01-09 17:10:08 +00:00
status = esci_set_gamma_table ( s ) ;
2006-12-02 14:47:21 +00:00
if ( status ! = SANE_STATUS_GOOD )
return status ;
}
/* ESC m, user defined color correction */
if ( s - > val [ OPT_COLOR_CORRECTION ] . w = = 1 ) {
2008-01-09 17:10:08 +00:00
status = esci_set_color_correction_coefficients ( s ) ;
2006-12-02 14:47:21 +00:00
if ( status ! = SANE_STATUS_GOOD )
return status ;
}
2006-12-18 00:13:09 +00:00
/* check if we just have finished working with the ADF.
* this seems to work only after the scanner has been
* set up with scanning parameters
*/
2008-01-09 17:10:08 +00:00
status = e2_check_adf ( s ) ;
2006-12-18 00:13:09 +00:00
if ( status ! = SANE_STATUS_GOOD )
return status ;
2006-12-02 14:47:21 +00:00
2006-12-12 01:12:07 +00:00
2006-12-18 00:13:09 +00:00
/*
status = sane_get_parameters ( handle , NULL ) ;
if ( status ! = SANE_STATUS_GOOD )
return status ;
*/
/*
* If WAIT_FOR_BUTTON is active , then do just that :
* Wait until the button is pressed . If the button was already
* pressed , then we will get the button pressed event right away .
*/
if ( s - > val [ OPT_WAIT_FOR_BUTTON ] . w = = SANE_TRUE )
2008-01-09 17:10:08 +00:00
e2_wait_button ( s ) ;
2006-12-02 14:47:21 +00:00
/* for debug, request command parameter */
2006-12-18 00:13:09 +00:00
/* if (DBG_LEVEL) {
2006-12-02 14:47:21 +00:00
unsigned char buf [ 45 ] ;
request_command_parameter ( s , buf ) ;
}
2006-12-18 00:13:09 +00:00
*/
2006-12-02 14:47:21 +00:00
/* set the retry count to 0 */
s - > retry_count = 0 ;
2006-12-18 00:13:09 +00:00
/* allocate buffers for color shuffling */
if ( dev - > color_shuffle = = SANE_TRUE ) {
2008-01-09 17:10:08 +00:00
int i ;
2006-12-02 14:47:21 +00:00
/* initialize the line buffers */
for ( i = 0 ; i < s - > line_distance * 2 + 1 ; i + + ) {
2009-06-01 14:18:52 +00:00
2006-12-02 14:47:21 +00:00
if ( s - > line_buffer [ i ] ! = NULL )
free ( s - > line_buffer [ i ] ) ;
s - > line_buffer [ i ] = malloc ( s - > params . bytes_per_line ) ;
if ( s - > line_buffer [ i ] = = NULL ) {
DBG ( 1 , " out of memory (line %d) \n " , __LINE__ ) ;
return SANE_STATUS_NO_MEM ;
}
}
}
2006-12-18 00:13:09 +00:00
/* prepare buffer here so that a memory allocation failure
* will leave the scanner in a sane state .
* the buffer will have to hold the image data plus
* an error code in the extended handshaking mode .
*/
s - > buf = realloc ( s - > buf , ( s - > lcount * s - > params . bytes_per_line ) + 1 ) ;
if ( s - > buf = = NULL )
return SANE_STATUS_NO_MEM ;
2006-12-02 14:47:21 +00:00
s - > eof = SANE_FALSE ;
s - > ptr = s - > end = s - > buf ;
s - > canceling = SANE_FALSE ;
2006-12-18 00:13:09 +00:00
/* feed the first sheet in the ADF */
if ( dev - > ADF & & dev - > use_extension & & dev - > cmd - > feed ) {
2008-01-09 17:10:08 +00:00
status = esci_feed ( s ) ;
2006-12-18 00:13:09 +00:00
if ( status ! = SANE_STATUS_GOOD )
return status ;
}
2006-12-02 14:47:21 +00:00
2006-12-18 00:13:09 +00:00
/* this seems to work only for some devices */
2008-01-09 17:10:08 +00:00
status = e2_wait_warm_up ( s ) ;
2006-12-18 00:13:09 +00:00
if ( status ! = SANE_STATUS_GOOD )
return status ;
2006-12-02 14:47:21 +00:00
2006-12-18 00:13:09 +00:00
/* start scanning */
DBG ( 1 , " %s: scanning... \n " , __func__ ) ;
2006-12-02 14:47:21 +00:00
2006-12-18 00:13:09 +00:00
if ( dev - > extended_commands ) {
2008-01-09 17:10:08 +00:00
status = e2_start_ext_scan ( s ) ;
2006-12-18 00:13:09 +00:00
2009-06-02 17:19:29 +00:00
/* sometimes the scanner gives an io error when
* it ' s warming up .
*/
if ( status = = SANE_STATUS_IO_ERROR ) {
2009-06-03 00:28:44 +00:00
status = e2_wait_warm_up ( s ) ;
if ( status = = SANE_STATUS_GOOD )
status = e2_start_ext_scan ( s ) ;
}
2008-01-09 17:10:08 +00:00
} else
status = e2_start_std_scan ( s ) ;
2006-12-18 00:13:09 +00:00
2007-11-18 09:36:04 +00:00
if ( status ! = SANE_STATUS_GOOD ) {
2006-12-18 00:13:09 +00:00
DBG ( 1 , " %s: start failed: %s \n " , __func__ ,
2008-01-09 17:10:08 +00:00
sane_strstatus ( status ) ) ;
2009-04-25 13:55:06 +00:00
return status ;
2008-01-09 17:10:08 +00:00
}
2006-12-18 00:13:09 +00:00
2009-04-25 13:55:06 +00:00
/* this is a kind of read request */
if ( dev - > connection = = SANE_EPSON_NET ) {
sanei_epson_net_write ( s , 0x2000 , NULL , 0 ,
s - > ext_block_len + 1 , & status ) ;
2009-06-03 00:28:44 +00:00
}
2006-12-18 00:13:09 +00:00
return status ;
2006-12-02 14:47:21 +00:00
}
static inline int
get_color ( int status )
{
switch ( ( status > > 2 ) & 0x03 ) {
case 1 :
return 1 ;
case 2 :
return 0 ;
case 3 :
return 2 ;
default :
return 0 ; /* required to make the compiler happy */
}
}
2009-06-01 14:18:52 +00:00
/* this moves data from our buffers to SANE */
2007-01-20 20:59:05 +00:00
2006-12-18 00:13:09 +00:00
SANE_Status
2009-06-03 00:28:44 +00:00
sane_read ( SANE_Handle handle , SANE_Byte * data , SANE_Int max_length ,
SANE_Int * length )
2006-12-18 00:13:09 +00:00
{
SANE_Status status ;
Epson_Scanner * s = ( Epson_Scanner * ) handle ;
2006-12-02 14:47:21 +00:00
2007-12-15 11:37:53 +00:00
* length = 0 ;
2006-12-18 00:13:09 +00:00
if ( s - > hw - > extended_commands )
2008-01-09 17:10:08 +00:00
status = e2_ext_sane_read ( handle ) ;
2006-12-18 00:13:09 +00:00
else
2008-01-09 17:10:08 +00:00
status = e2_block_sane_read ( handle ) ;
2007-01-20 20:59:05 +00:00
2009-06-03 16:52:59 +00:00
DBG ( 18 , " moving data %d %p %p \n " , max_length , s - > ptr , s - > end ) ;
2008-01-09 17:10:08 +00:00
e2_copy_image_data ( s , data , max_length , length ) ;
2006-12-02 14:47:21 +00:00
2006-12-18 00:13:09 +00:00
/* continue reading if appropriate */
if ( status = = SANE_STATUS_GOOD )
return status ;
2006-12-02 14:47:21 +00:00
2008-01-09 17:10:08 +00:00
e2_scan_finish ( s ) ;
2006-12-02 14:47:21 +00:00
2006-12-18 00:13:09 +00:00
return status ;
2006-12-02 14:47:21 +00:00
}
/*
* void sane_cancel ( SANE_Handle handle )
*
* Set the cancel flag to true . The next time the backend requests data
* from the scanner the CAN message will be sent .
*/
void
sane_cancel ( SANE_Handle handle )
{
Epson_Scanner * s = ( Epson_Scanner * ) handle ;
2008-01-09 17:10:08 +00:00
SANE_Status status = SANE_STATUS_GOOD ;
2006-12-02 14:47:21 +00:00
/*
* If the s - > ptr pointer is not NULL , then a scan operation
* was started and if s - > eof is FALSE , it was not finished .
*/
2007-01-20 20:59:05 +00:00
if ( s - > buf ) {
2006-12-02 14:47:21 +00:00
unsigned char * dummy ;
int len ;
/* malloc one line */
dummy = malloc ( s - > params . bytes_per_line ) ;
if ( dummy = = NULL ) {
DBG ( 1 , " Out of memory \n " ) ;
return ;
2009-06-01 14:18:52 +00:00
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* there is still data to read from the scanner */
s - > canceling = SANE_TRUE ;
/* XXX check this condition, we used to check
* for SANE_STATUS_CANCELLED */
while ( ! s - > eof & &
( status = = SANE_STATUS_GOOD
| | status = = SANE_STATUS_DEVICE_BUSY ) ) {
/* empty body, the while condition does the processing */
2009-06-03 00:28:44 +00:00
/* XXX ? */
2009-06-01 14:18:52 +00:00
status = sane_read ( s , dummy ,
s - > params . bytes_per_line ,
& len ) ;
2006-12-02 14:47:21 +00:00
}
2009-06-01 14:18:52 +00:00
free ( dummy ) ;
2006-12-02 14:47:21 +00:00
}
}
static void
2009-06-03 00:28:44 +00:00
filter_resolution_list ( Epson_Scanner * s )
2006-12-02 14:47:21 +00:00
{
2009-06-01 14:18:52 +00:00
int i , new_size = 0 ;
2009-06-03 00:28:44 +00:00
2009-06-01 14:18:52 +00:00
struct Epson_Device * dev = s - > hw ;
SANE_Bool is_correct_resolution = SANE_FALSE ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
if ( s - > val [ OPT_LIMIT_RESOLUTION ] . w = = SANE_FALSE ) {
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
/* copy the full list */
dev - > resolution_list [ 0 ] = dev - > res_list_size ;
memcpy ( & ( dev - > resolution_list [ 1 ] ) , dev - > res_list ,
dev - > res_list_size * sizeof ( SANE_Word ) ) ;
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
return ;
2009-06-03 00:28:44 +00:00
}
2006-12-02 14:47:21 +00:00
2009-06-03 00:28:44 +00:00
/* shorten the list */
2009-06-01 14:18:52 +00:00
/* filter out all values that are not 300 or 400 dpi based */
for ( i = 0 ; i < dev - > res_list_size ; i + + ) {
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
SANE_Word res = dev - > res_list [ i ] ;
if ( ( res < 100 ) | | res = = 150 | | ( ( res % 300 ) = = 0 )
2009-06-03 00:28:44 +00:00
| | ( ( res % 400 ) = = 0 ) ) {
2009-06-01 14:18:52 +00:00
/* add the value */
new_size + + ;
dev - > resolution_list [ new_size ] =
dev - > res_list [ i ] ;
/* check for a valid current resolution */
if ( res = = s - > val [ OPT_RESOLUTION ] . w )
is_correct_resolution = SANE_TRUE ;
2006-12-02 14:47:21 +00:00
}
2009-06-01 14:18:52 +00:00
}
2006-12-02 14:47:21 +00:00
2009-06-01 14:18:52 +00:00
dev - > resolution_list [ 0 ] = new_size ;
/* if the current resolution is invalid, accordingly
* to the filtered list , search for a suitable one
*/
if ( is_correct_resolution = = SANE_TRUE )
2009-06-03 00:28:44 +00:00
return ;
2009-06-01 14:18:52 +00:00
for ( i = 1 ; i < = new_size ; i + + ) {
if ( s - > val [ OPT_RESOLUTION ] . w < dev - > resolution_list [ i ] ) {
s - > val [ OPT_RESOLUTION ] . w = dev - > resolution_list [ i ] ;
break ;
}
2006-12-02 14:47:21 +00:00
}
}
/*
* SANE_Status sane_set_io_mode ( )
*
* not supported - for asynchronous I / O
*/
SANE_Status
2009-06-01 14:18:52 +00:00
sane_set_io_mode ( SANE_Handle __sane_unused__ handle ,
2009-06-03 00:28:44 +00:00
SANE_Bool __sane_unused__ non_blocking )
2006-12-02 14:47:21 +00:00
{
return SANE_STATUS_UNSUPPORTED ;
}
/*
* SANE_Status sane_get_select_fd ( )
*
* not supported - for asynchronous I / O
*/
SANE_Status
2009-06-01 14:18:52 +00:00
sane_get_select_fd ( SANE_Handle __sane_unused__ handle ,
2009-06-03 00:28:44 +00:00
SANE_Int __sane_unused__ * fd )
2006-12-02 14:47:21 +00:00
{
return SANE_STATUS_UNSUPPORTED ;
}