2012-07-01 01:28:14 +00:00
/*
* kodakaio . c - SANE library for Kodak ESP Aio scanners .
*
2014-12-31 10:26:07 +00:00
* Copyright ( C ) 2011 - 2015 Paul Newall
2012-07-01 01:28:14 +00:00
*
2012-12-09 23:29:07 +00:00
* Based on the Magicolor sane backend :
2012-07-01 01:28:14 +00:00
* Based on the epson2 sane backend :
* Based on Kazuhiro Sasayama previous
* work on epson . [ ch ] file from the SANE package .
* Please see those files for additional copyrights .
* Author : Paul Newall
*
* 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.
2012-11-28 21:35:36 +00:00
2014-12-31 10:26:07 +00:00
* Modified 30 / 12 / 14 to fix bug where network connection was broken after 30 s of idle time .
* The connection is now made in sane_start and ended in sane_cancel .
2013-01-03 21:23:20 +00:00
* 01 / 01 / 13 Now with adf , the scan can be padded to make up the full page length ,
* or the page can terminate at the end of the paper . This is a selectable option .
2014-12-31 10:26:07 +00:00
* 25 / 11 / 12 Using avahi now for net autodiscovery . Use configure option - - enable - avahi
2012-07-01 01:28:14 +00:00
*/
2014-12-19 22:52:48 +00:00
/*
Packages to add to a clean ubuntu install
libavahi - common - dev
libusb - dev
libsnmp - dev
convenient lines to paste
2014-09-13 22:26:04 +00:00
export SANE_DEBUG_KODAKAIO = 20
2012-11-28 21:35:36 +00:00
for ubuntu prior to 12.10
2014-05-30 20:19:13 +00:00
. / configure - - prefix = / usr - - sysconfdir = / etc - - localstatedir = / var - - enable - avahi - - disable - latex BACKENDS = " kodakaio test "
2012-11-28 21:35:36 +00:00
for ubuntu 12.10
2014-05-30 20:19:13 +00:00
. / configure - - prefix = / usr - - libdir = / usr / lib / i386 - linux - gnu - - sysconfdir = / etc - - localstatedir = / var - - enable - avahi - - disable - latex BACKENDS = " kodakaio test "
2014-12-19 22:52:48 +00:00
for ubuntu 14.10
. / configure - - prefix = / usr - - libdir = / usr / lib / x86_64 - linux - gnu - - sysconfdir = / etc - - localstatedir = / var - - enable - avahi - - disable - latex BACKENDS = " kodakaio test "
2014-05-30 20:19:13 +00:00
If you want to use the test backend , for example with sane - troubleshoot , you should enable it in / etc / sane . d / dll . conf
2012-11-28 21:35:36 +00:00
2012-07-01 01:28:14 +00:00
*/
/* SANE-FLOW-DIAGRAM Kodakaio commands in [] brackets
2012-11-28 21:35:36 +00:00
2012-07-01 01:28:14 +00:00
- sane_init ( ) : initialize backend , attach scanners ( devicename , 0 )
. - sane_get_devices ( ) : query list of scanner - devices
. - sane_open ( ) : open a particular scanner - device and attach_scanner ( devicename , & dev )
. . - sane_set_io_mode : set blocking - mode
. . - sane_get_select_fd : get scanner - fd
. . - sane_get_option_descriptor ( ) : get option informations
. . - sane_control_option ( ) : change option values
. .
. . - sane_start ( ) : start image aquisition [ V , L , F , S , C , D , O , Z ] first time or after cancel . [ ( F ) , E , G ] every time
. . - sane_get_parameters ( ) : returns actual scan - parameters
. . - sane_read ( ) : read image - data ( from pipe )
. . - sane_cancel ( ) : cancel operation , kill reader_process [ ( F ) , U ]
2012-12-23 21:23:43 +00:00
. - sane_close ( ) : close opened scanner - device , do_cancel , free buffer and handle
2012-07-01 01:28:14 +00:00
- sane_exit ( ) : terminate use of backend , free devicename and device - struture
*/
/* FUNCTION-TREE
sane_init
sane_open
device_detect
2014-12-31 10:26:07 +00:00
k_dev_init
open_scanner
close_scanner
2012-07-01 01:28:14 +00:00
sane_get_devices
init_options
2014-12-31 10:26:07 +00:00
( open_scanner - moved to sane_start 27 / 12 / 14 )
2012-07-01 01:28:14 +00:00
sane_control_option
getvalue
setvalue
search_string_list
change_source
activateOption
deactivateOption
2014-12-31 10:26:07 +00:00
sane_start
open_scanner
k_init_parametersta
k_lock_scanner
k_hello
k_set_scanning_parameters
print_params
k_start_scan
cmd_start_scan
print_status
k_send
kodakaio_txrxack
2012-07-01 01:28:14 +00:00
sane_get_parameters
print_params
sane_read
k_read
2012-12-31 20:13:32 +00:00
cmd_read_data ( reads one block )
2012-07-01 01:28:14 +00:00
k_recv
cmp_array
2014-12-31 10:26:07 +00:00
sane_cancel
cmd_cancel_scan
close_scanner
sane_close
( close_scanner - moved to sane_cancel 27 / 12 / 14 )
2012-07-01 01:28:14 +00:00
sane_exit
free_devices
k_recv
kodakaio_net_read
dump_hex_buffer_dense
k_send
sanei_kodakaio_net_write_raw
dump_hex_buffer_dense
open_scanner
sanei_kodakaio_net_open
close_scanner
2014-12-31 10:26:07 +00:00
k_scan_finish
cmd_cancel_scan
sanei_kodakaio_net_close or sanei_usb_close
2012-07-01 01:28:14 +00:00
detect_usb
kodakaio_getNumberOfUSBProductIds
attach_one_config - ( Passed to sanei_configure_attach )
kodakaio_getNumberOfUSBProductIds
kodak_network_discovery
2012-11-28 21:35:36 +00:00
client_callback
browse_callback
resolve_callback
ProcessAvahiDevice
2012-07-01 01:28:14 +00:00
attach_one_net
attach_one_net
attach
device_detect
attach_one_usb - ( passed to sanei_usb_find_devices )
attach
device_detect
k_lock_scanner
kodakaio_txrx
k_send
k_recv
kodakaio_txrxack
k_send
k_recv
cmd_set_color_curve
kodakaio_expect_ack
k_recv
cmd_cancel_scan
kodakaio_txrxack
cmd_set_scanning_parameters
kodakaio_txrxack
device_detect
k_dev_init
*/
# define KODAKAIO_VERSION 02
2014-12-19 22:52:48 +00:00
# define KODAKAIO_REVISION 7
2014-12-31 10:26:07 +00:00
# define KODAKAIO_BUILD 2
2012-07-01 01:28:14 +00:00
2012-12-31 20:13:32 +00:00
/* for usb (but also used for net though it's not required). */
2012-12-23 21:23:43 +00:00
# define MAX_BLOCK_SIZE 32768
2012-12-31 20:13:32 +00:00
2012-07-01 01:28:14 +00:00
# define SCANNER_READ_TIMEOUT 15
2012-12-31 20:13:32 +00:00
/* POLL_ITN_MS sets the individual poll timeout for network discovery */
2012-11-28 21:35:36 +00:00
# define POLL_ITN_MS 20
2012-07-01 01:28:14 +00:00
/* debugging levels:
In terminal use : export SANE_DEBUG_KODAKAIO = 40 to set the level to 40 or whatever
level you want .
2012-12-23 21:23:43 +00:00
Then you can scan with scanimage or simple - scan from terminal and see debug info
2012-07-01 01:28:14 +00:00
use these defines to promote certain functions that you are interested in
define low values to make detail of a section appear when DBG level is low
define a high value eg 99 to get normal behaviour . */
# define DBG_READ 99
2012-11-28 21:35:36 +00:00
# define DBG_AUTO 99 /* for autodiscovery */
2012-07-01 01:28:14 +00:00
/*
normal levels . This system is a plan rather than a reality
*
* 127 recv buffer
* 125 send buffer
* 35 fine - grained status and progress
* 30 sane_read
* 25 setvalue , getvalue , control_option
2012-12-23 21:23:43 +00:00
* 20 low - level ( I / O ) functions
2012-07-01 01:28:14 +00:00
* 15 mid - level functions
* 10 high - level functions
* 7 open / close / attach
* 6 print_params
* 5 basic functions
* 3 status info and progress
* 2 sane api
* 1 errors & warnings
*/
# include "sane/config.h"
# include <limits.h>
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <ctype.h>
# include <fcntl.h>
# include <unistd.h>
# include <errno.h>
# include <sys/time.h>
# include <math.h>
# include <poll.h>
# include <time.h>
2012-11-28 21:35:36 +00:00
# if WITH_AVAHI
2012-07-01 01:28:14 +00:00
/* used for auto detecting network printers */
2012-11-28 21:35:36 +00:00
# include <assert.h>
# include <avahi-client/client.h>
# include <avahi-client/lookup.h>
# include <avahi-common/simple-watch.h>
# include <avahi-common/malloc.h>
# include <avahi-common/error.h>
static AvahiSimplePoll * simple_poll = NULL ; /* global because called by several functions */
2012-07-01 01:28:14 +00:00
# endif
# include "../include/sane/saneopts.h"
# include "../include/sane/sanei_usb.h"
# include "../include/sane/sanei_tcp.h"
# include "../include/sane/sanei_udp.h"
# include "../include/sane/sanei_config.h"
# include "../include/sane/sanei_backend.h"
# include "kodakaio.h"
/* vendor and product ids that are allowed */
# define SANE_KODAKAIO_VENDOR_ID (0x040a)
# define min(x,y) (((x)<(y))?(x):(y))
2012-11-28 21:35:36 +00:00
/* I think these timeouts (ms) are defaults, overridden by any timeouts in the kodakaio.conf file */
static int K_SNMP_Timeout = 3000 ; /* used for any auto detection method */
2012-12-31 20:13:32 +00:00
static int K_Scan_Data_Timeout = 10000 ;
2012-08-09 15:33:41 +00:00
static int K_Request_Timeout = 5000 ;
2012-07-01 01:28:14 +00:00
2015-09-13 18:34:17 +00:00
/* static int bitposn=0; was used to pack bits into bytes in lineart mode */
2014-09-13 22:26:04 +00:00
2012-07-01 01:28:14 +00:00
/* This file is used to store directly the raster returned by the scanner for debugging
If RawScanPath has no length it will not be created */
FILE * RawScan = NULL ;
2014-12-31 10:26:07 +00:00
/* example: char RawScanPath[] = "TestRawScan.pgm"; */
2012-11-28 21:35:36 +00:00
char RawScanPath [ ] = " " ; /* empty path means no raw scan file is made */
2012-07-01 01:28:14 +00:00
2012-12-23 21:23:43 +00:00
/*
* Devices supported by this backend
*/
2012-07-01 01:28:14 +00:00
/* kodak command strings */
static unsigned char KodakEsp_V [ ] = { 0x1b , ' S ' , ' V ' , 0 , 0 , 0 , 0 , 0 } ; /* version?? */
static unsigned char KodakEsp_v [ ] = { 0x1b , ' s ' , ' v ' , 0 , 0 , 0 , 0 , 0 } ; /* reply to version?? */
static unsigned char KodakEsp_Lock [ ] = { 0x1b , ' S ' , ' L ' , 0 , 0 , 0 , 0 , 0 } ; /* Locks scanner */
static unsigned char KodakEsp_UnLock [ ] = { 0x1b , ' S ' , ' U ' , 0 , 0 , 0 , 0 , 0 } ; /* Unlocks scanner */
static unsigned char KodakEsp_Ack [ ] = { 0x1b , ' S ' , ' S ' , 0 , 0 , 0 , 0 , 0 } ; /* Acknowledge for all commands */
2012-12-31 20:13:32 +00:00
/* the bytes after esc S S 0 may indicate status: S S 0 1 = docs in adf */
2012-07-01 01:28:14 +00:00
static unsigned char KodakEsp_F [ ] = { 0x1b , ' S ' , ' F ' , 0 , 0 , 0 , 0 , 0 } ; /* Purpose not known? colour balance?*/
static unsigned char KodakEsp_Comp [ ] = { 0x1b , ' S ' , ' C ' , 3 , 8 , 3 , 0 , 0 } ; /* 3,8,3,1,0 does compression. */
/* The compression method is unknown */
/* static unsigned char KodakEsp_E[] = {0x1b,'S','E',1,0,0,0,0}; NET Purpose not known */
/* the extra 1 below could be despeckle option? maybe only for Hero 9.1 but no errors with ESP5250 */
static unsigned char KodakEsp_E [ ] = { 0x1b , ' S ' , ' E ' , 1 , 1 , 0 , 0 , 0 } ;
static unsigned char KodakEsp_Go [ ] = { 0x1b , ' S ' , ' G ' , 0 , 0 , 0 , 0 , 0 } ; /* Starts the scan */
/* Other commands are: D (resolution), O (top left), Z (bottom right), R, G, B (curves) */
/* What is the relationship between these and the ranges in cap? */
static SANE_Int kodakaio_resolution_list [ ] = { 75 , 150 , 300 , 600 , 1200 } ;
static SANE_Int kodakaio_depth_list [ ] = { 1 , 8 } ; /* The first value is the number of following entries */
2012-11-28 21:35:36 +00:00
/* strings to try and match the model ';' separator
static unsigned char SupportedMatchString [ ] = " KODAK ESP;KODAK HERO;KODAK OFFICE HERO;ADVENT WiFi AIO; " ; */
2012-07-01 01:28:14 +00:00
static struct KodakaioCap kodakaio_cap [ ] = {
/* usbid,commandtype, modelname, USBoutEP, USBinEP,
opticalres , { dpi range } , pointer to res list , res list size
max depth , pointer to depth list ,
flatbed x range , flatbed y range ,
adf present , adf duplex ,
2012-12-23 21:23:43 +00:00
adf x range , adf y range ( y range should be set a little shorter than the paper being scanned )
2012-07-01 01:28:14 +00:00
The following are not used but may be in future
commandtype , max depth , pointer to depth list
*/
/* list of cap data the first scanner is the default
*/
/* KODAK AIO DEFAULT, */
{
0x9999 , " esp " , " KODAK AIO DEFAULT " ,
- 1 , 0x82 , /* USBoutEP, USBinEP (-1 means find one) */
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_FALSE , /* ADF, duplex */
{ 0 , SANE_FIX ( 100 ) , 0 } , { 0 , SANE_FIX ( 100 ) , 0 } /* ADF x/y ranges (TODO!) */
} ,
/* KODAK ESP 5100, */
{
0x4025 , " esp " , " KODAK ESP 5100 AiO " ,
- 1 , 0x82 , /* USBoutEP, USBinEP (-1 means find one) */
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP 5300, */
{
0x4026 , " esp " , " KODAK ESP 5300 AiO " ,
- 1 , 0x82 , /* USBoutEP, USBinEP (-1 means find one) */
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP 5500, */
{
0x4027 , " esp " , " KODAK ESP 5500 AiO " ,
- 1 , 0x82 , /* USBoutEP, USBinEP (-1 means find one) */
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP 5000, */
{
0x4028 , " esp " , " KODAK ESP 5000 Series AiO " ,
- 1 , 0x82 , /* USBoutEP, USBinEP (-1 means find one) */
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP 3300, */
{
0x4031 , " esp " , " KODAK ESP 3300 Series AiO " ,
- 1 , 0x82 , /* USBoutEP, USBinEP (-1 means find one) */
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP5, */
{
0x4032 , " esp " , " KODAK ESP 5 AiO " ,
- 1 , 0x82 , /* USBoutEP, USBinEP (-1 means find one) */
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP7, */
{
0x403E , " esp " , " KODAK ESP 7 AiO " ,
- 1 , 0x82 , /* USBoutEP, USBinEP (-1 means find one) */
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP9, */
{
0x403F , " esp " , " KODAK ESP 9 AiO " ,
- 1 , 0x82 , /* USBoutEP, USBinEP (-1 means find one) */
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP5210 or 5250, */
{
0x4041 , " esp " , " KODAK ESP 5200 Series AiO " ,
- 1 , 0x82 , /* USBoutEP, USBinEP (-1 means find one) */
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP3200 , */
{
0x4043 , " esp " , " KODAK ESP 3200 Series AiO " ,
- 1 , 0x82 ,
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP4100 , */
{
0x4053 , " esp " , " KODAK ESP Office 4100 Series AiO " ,
- 1 , 0x82 ,
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP6100 , */
{
0x4054 , " esp " , " KODAK ESP Office 6100 Series AiO " ,
- 1 , 0x82 ,
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_TRUE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP7200 , */
{
0x4056 , " esp " , " KODAK ESP 7200 Series AiO " ,
- 1 , 0x82 ,
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP C110 , */
{
0x4057 , " esp " , " KODAK ESP C110 AiO " ,
- 1 , 0x82 ,
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP C115 , */
{
0x4058 , " esp " , " KODAK ESP C115 AiO " ,
- 1 , 0x82 ,
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP 2150 , */
{
0x4059 , " esp " , " KODAK ESP Office 2150 Series " ,
- 1 , 0x82 ,
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_TRUE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP C310 , */
{
0x405D , " esp " , " KODAK ESP C310 AiO " ,
- 1 , 0x82 ,
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP C315 , */
{
0x405E , " esp " , " KODAK ESP C315 AiO " ,
- 1 , 0x82 ,
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* ADVENT AW10, */
{
0x4060 , " esp " , " ADVENT WiFi AIO AW10 " ,
- 1 , 0x82 ,
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, {from, to, 0} 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_TRUE , SANE_FALSE , /* ADF, duplex. */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK HERO 6.1, */
{
0x4062 , " esp " , " KODAK OFFICE HERO 6.1 AiO " ,
- 1 , 0x82 ,
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, {from, to, 0} 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_TRUE , SANE_FALSE , /* ADF, duplex. */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK HERO 7.1, */
{
0x4063 , " esp " , " KODAK HERO 7.1 AiO " ,
- 1 , 0x82 ,
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, {from, to, 0} 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_TRUE , /* ADF, duplex. */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK HERO 5.1, */
{
0x4064 , " esp " , " KODAK HERO 5.1 AiO " ,
- 1 , 0x82 ,
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, {from, to, 0} 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_FALSE , SANE_TRUE , /* ADF, duplex.*/
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP9200 , */
{
0x4065 , " esp " , " KODAK ESP 9200 Series AiO " ,
- 1 , 0x82 ,
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_TRUE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK ESP2170 , */
{
0x4066 , " esp " , " KODAK ESP Office 2170 Series " ,
- 1 , 0x82 ,
2012-12-31 20:13:32 +00:00
1200 , { 75 , 1200 , 0 } , kodakaio_resolution_list , 5 , /* 1200 dpi optical, {from, to, 0} 5 resolutions */
2012-07-01 01:28:14 +00:00
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
2012-12-09 23:29:07 +00:00
SANE_TRUE , SANE_FALSE , /* ADF, duplex */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* KODAK HERO 9.1, */
{
0x4067 , " esp " , " KODAK HERO 9.1 AiO " ,
- 1 , 0x82 ,
2012-12-31 20:13:32 +00:00
1200 , { 75 , 1200 , 0 } , kodakaio_resolution_list , 5 , /* 1200 dpi optical, {from, to, 0} 5 resolutions */
2012-07-01 01:28:14 +00:00
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_TRUE , SANE_FALSE , /* ADF, duplex. */
2012-12-31 20:13:32 +00:00
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
2013-01-19 21:41:40 +00:00
/* KODAK HERO 4.1, */
{
0x4069 , " esp " , " KODAK HERO 4.1 AiO " ,
- 1 , 0x82 ,
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, {from, to, 0} 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
SANE_TRUE , SANE_FALSE , /* ADF, duplex.*/
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
} ,
2012-07-01 01:28:14 +00:00
/* KODAK HERO 3.1, */
{
0x406D , " esp " , " KODAK HERO 3.1 AiO " ,
- 1 , 0x82 ,
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, {from, to, 0} 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
2012-12-31 20:13:32 +00:00
SANE_FALSE , SANE_TRUE , /* ADF, duplex. */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
} ,
/* spare use for specified usbid */
{
0 , " esp " , " specified " ,
- 1 , 0x82 ,
600 , { 75 , 600 , 0 } , kodakaio_resolution_list , 4 , /* 600 dpi max, {from, to, 0} 4 resolutions */
8 , kodakaio_depth_list , /* color depth max 8, list above */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 11.7 * MM_PER_INCH ) , 0 } , /* FBF x/y ranges */
2012-12-31 20:13:32 +00:00
SANE_FALSE , SANE_TRUE , /* ADF, duplex. */
{ 0 , SANE_FIX ( 8.5 * MM_PER_INCH ) , 0 } , { 0 , SANE_FIX ( 14 * MM_PER_INCH ) , 0 } /* 14 ADF x/y ranges */
2012-07-01 01:28:14 +00:00
}
} ;
/****************************************************************************
2012-11-28 21:35:36 +00:00
* General configuration parameter definitions * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-07-01 01:28:14 +00:00
/*
* 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 .
*/
2014-09-13 22:26:04 +00:00
/* could be affecting what data sane delivers */
2012-07-01 01:28:14 +00:00
static struct mode_param mode_params [ ] = {
2014-12-19 22:52:48 +00:00
{ 0x03 , 3 , 24 } , /* Color, 3 colors, 24 bit */
2012-07-01 01:28:14 +00:00
{ 0x02 , 1 , 8 } , /* Grayscale, 1 color, 8 bit */
2014-12-19 22:52:48 +00:00
{ 0x00 , 1 , 1 } /* Lineart, 1 color, 8 bit (was 8 bit) */
2012-07-01 01:28:14 +00:00
} ;
static SANE_String_Const mode_list [ ] = {
SANE_VALUE_SCAN_MODE_COLOR ,
2014-12-19 22:52:48 +00:00
SANE_VALUE_SCAN_MODE_GRAY ,
SANE_VALUE_SCAN_MODE_LINEART ,
2012-07-01 01:28:14 +00:00
NULL
} ;
static const SANE_String_Const adf_mode_list [ ] = {
SANE_I18N ( " Simplex " ) ,
SANE_I18N ( " Duplex " ) ,
NULL
} ;
/* Define the different scan sources */
# define FBF_STR SANE_I18N("Flatbed")
# define ADF_STR SANE_I18N("Automatic Document Feeder")
/*
* 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 . Here space is reserved for 3 entries + NULL ?
*/
static SANE_String_Const source_list [ ] = {
FBF_STR ,
NULL ,
NULL ,
NULL
} ;
2014-09-13 22:26:04 +00:00
static const SANE_Range percent_range_fixed = { SANE_FIX ( 0.0 ) , SANE_FIX ( 100.0 ) , SANE_FIX ( 1.0 ) } ;
2015-09-23 11:11:51 +00:00
/*static const SANE_Range percent_range_int = {0, 100, 1};*/
2014-09-13 22:26:04 +00:00
2012-07-01 01:28:14 +00:00
/* prototypes */
static SANE_Status attach_one_usb ( SANE_String_Const devname ) ;
static SANE_Status attach_one_net ( SANE_String_Const devname , unsigned int device ) ;
void kodakaio_com_str ( unsigned char * buf , char * fmt_buf ) ;
int cmparray ( unsigned char * array1 , unsigned char * array2 , size_t len ) ;
2012-11-28 21:35:36 +00:00
static struct KodakaioCap * get_device_from_identification ( const char * ident , const char * vid , const char * pid ) ;
void ProcessAvahiDevice ( const char * device_id , const char * vid , const char * pid , const char * ip_addr ) ;
2012-07-01 01:28:14 +00:00
/* Some utility functions */
static size_t
max_string_size ( const SANE_String_Const strings [ ] )
{
/* returns the length of the longest string in an array of 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 ;
}
2012-12-31 20:13:32 +00:00
2012-07-01 01:28:14 +00:00
static void
2012-12-23 21:23:43 +00:00
print_params ( const SANE_Parameters params , int level )
2012-07-01 01:28:14 +00:00
{
2012-12-23 21:23:43 +00:00
DBG ( level , " formats: binary=?, grey=%d, colour=%d \n " , SANE_FRAME_GRAY , SANE_FRAME_RGB ) ;
DBG ( level , " params.format = %d \n " , params . format ) ;
DBG ( level , " params.last_frame = %d \n " , params . last_frame ) ;
DBG ( level , " params.bytes_per_line = %d \n " , params . bytes_per_line ) ;
DBG ( level , " params.pixels_per_line = %d \n " , params . pixels_per_line ) ;
DBG ( level , " params.lines = %d \n " , params . lines ) ;
DBG ( level , " params.depth = %d \n " , params . depth ) ;
2012-07-01 01:28:14 +00:00
}
static void
print_status ( KodakAio_Scanner * s , int level )
{
DBG ( level , " print_status with level %d \n " , level ) ;
DBG ( level , " s->bytes_unread = %d \n " , s - > bytes_unread ) ;
/*
DBG ( level , " params.last_frame = %d \n " , params . last_frame ) ;
DBG ( level , " params.bytes_per_line = %d \n " , params . bytes_per_line ) ;
DBG ( level , " params.pixels_per_line = %d \n " , params . pixels_per_line ) ;
DBG ( level , " params.lines = %d \n " , params . lines ) ;
DBG ( level , " params.depth = %d \n " , params . depth ) ;
*/
}
/****************************************************************************
2012-11-28 21:35:36 +00:00
* Low - level Network communication functions * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-07-01 01:28:14 +00:00
static int
kodakaio_net_read ( struct KodakAio_Scanner * s , unsigned char * buf , size_t wanted ,
SANE_Status * status )
2014-12-31 10:26:07 +00:00
/* there seems to be a condition where this returns no error and no data without detecting a timeout
That is probably if the scanner disconnected the network connection
*/
2012-07-01 01:28:14 +00:00
{
size_t size , read = 0 ;
struct pollfd fds [ 1 ] ;
2012-08-09 15:33:41 +00:00
int pollreply ;
2012-07-01 01:28:14 +00:00
* status = SANE_STATUS_GOOD ;
2012-08-09 15:33:41 +00:00
/* poll for data-to-be-read (using K_Request_Timeout) */
2012-07-01 01:28:14 +00:00
fds [ 0 ] . fd = s - > fd ;
fds [ 0 ] . events = POLLIN ;
2012-08-09 15:33:41 +00:00
fds [ 0 ] . revents = 0 ;
2012-11-28 21:35:36 +00:00
if ( ( pollreply = poll ( fds , 1 , K_Request_Timeout ) ) < = 0 ) {
2014-12-31 10:26:07 +00:00
if ( pollreply = = 0 )
2012-12-23 21:23:43 +00:00
DBG ( 1 , " net poll timeout \n " ) ;
2012-08-09 15:33:41 +00:00
else
2012-12-23 21:23:43 +00:00
/* pollreply is -ve */
DBG ( 1 , " net poll error \n " ) ;
2012-07-01 01:28:14 +00:00
* status = SANE_STATUS_IO_ERROR ;
return read ;
}
2014-12-31 10:26:07 +00:00
else if ( ( fds [ 0 ] . revents & POLLIN ) & & ! ( fds [ 0 ] . revents & ( POLLERR | POLLHUP | POLLNVAL ) ) ) {
2012-08-09 15:33:41 +00:00
while ( read < wanted ) {
2015-09-23 11:49:46 +00:00
DBG ( 50 , " reading: read %lu, wanted %lu \n " , read , wanted ) ;
2012-08-09 15:33:41 +00:00
size = sanei_tcp_read ( s - > fd , buf + read , wanted - read ) ;
2014-12-31 10:26:07 +00:00
if ( size = = 0 ) {
DBG ( 1 , " No data read. Scanner may have disconnected \n " ) ;
break ;
}
2012-08-09 15:33:41 +00:00
read + = size ;
}
2012-07-01 01:28:14 +00:00
2014-12-31 10:26:07 +00:00
if ( read = = 0 )
2012-08-09 15:33:41 +00:00
* status = SANE_STATUS_IO_ERROR ;
2014-12-31 10:26:07 +00:00
2012-08-09 15:33:41 +00:00
DBG ( 32 , " net read %d bytes:%x,%x,%x,%x,%x,%x,%x,%x \n " , read , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] , buf [ 3 ] , buf [ 4 ] , buf [ 5 ] , buf [ 6 ] , buf [ 7 ] ) ;
2014-12-31 10:26:07 +00:00
2012-08-09 15:33:41 +00:00
return read ;
}
else
DBG ( 1 , " Unknown problem with poll \n " ) ;
2012-11-28 21:35:36 +00:00
return read ;
2012-07-01 01:28:14 +00:00
}
2014-12-31 10:26:07 +00:00
2012-07-01 01:28:14 +00:00
static int
sanei_kodakaio_net_write_raw ( struct KodakAio_Scanner * s ,
const unsigned char * buf , size_t buf_size ,
SANE_Status * status )
{
DBG ( 32 , " net write:%x,%x,%x,%x,%x,%x,%x,%x \n " , buf [ 0 ] , buf [ 1 ] , buf [ 2 ] , buf [ 3 ] , buf [ 4 ] , buf [ 5 ] , buf [ 6 ] , buf [ 7 ] ) ;
sanei_tcp_write ( s - > fd , buf , buf_size ) ;
/* TODO: Check whether sending failed... */
* status = SANE_STATUS_GOOD ;
return buf_size ;
}
static SANE_Status
sanei_kodakaio_net_open ( struct KodakAio_Scanner * s )
{
struct timeval tv ;
tv . tv_sec = 5 ;
tv . tv_usec = 0 ;
2012-12-23 21:23:43 +00:00
DBG ( 5 , " %s \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
setsockopt ( s - > fd , SOL_SOCKET , SO_RCVTIMEO , ( char * ) & tv , sizeof ( tv ) ) ;
return SANE_STATUS_GOOD ;
}
static SANE_Status
sanei_kodakaio_net_close ( struct KodakAio_Scanner * s )
{
NOT_USED ( s ) ;
/* Does nothing - maybe should close the socket ? */
return SANE_STATUS_GOOD ;
}
/****************************************************************************
2012-11-28 21:35:36 +00:00
* Low - level USB communication functions * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-07-01 01:28:14 +00:00
static int
kodakaio_getNumberOfUSBProductIds ( void )
{
return sizeof ( kodakaio_cap ) / sizeof ( struct KodakaioCap ) ;
}
/****************************************************************************
2012-11-28 21:35:36 +00:00
* low - level communication commands * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-07-01 01:28:14 +00:00
static void dump_hex_buffer_dense ( int level , const unsigned char * buf , size_t buf_size )
{
size_t k ;
char msg [ 1024 ] , fmt_buf [ 1024 ] ;
memset ( & msg [ 0 ] , 0x00 , 1024 ) ;
memset ( & fmt_buf [ 0 ] , 0x00 , 1024 ) ;
for ( k = 0 ; k < min ( buf_size , 80 ) ; k + + ) {
if ( k % 16 = = 0 ) {
if ( k > 0 ) {
DBG ( level , " %s \n " , msg ) ;
memset ( & msg [ 0 ] , 0x00 , 1024 ) ;
}
sprintf ( fmt_buf , " 0x%04lx " , ( unsigned long ) k ) ;
strcat ( msg , fmt_buf ) ;
}
if ( k % 8 = = 0 ) {
strcat ( msg , " " ) ;
}
sprintf ( fmt_buf , " %02x " , buf [ k ] ) ;
strcat ( msg , fmt_buf ) ;
}
if ( msg [ 0 ] ! = 0 ) {
DBG ( level , " %s \n " , msg ) ;
}
}
/* changing params to char seems to cause a stack problem */
void kodakaio_com_str ( unsigned char * buf , char * fmt_buf )
{
/* returns a printable string version of the first 8 bytes assuming they are a kodakaio command*/
if ( buf [ 0 ] = = 0x1b ) {
sprintf ( fmt_buf , " esc %c %c %02x %02x %02x %02x %02x " ,
buf [ 1 ] , buf [ 2 ] , buf [ 3 ] , buf [ 4 ] , buf [ 5 ] , buf [ 6 ] , buf [ 7 ] ) ;
}
else {
sprintf ( fmt_buf , " %02x %02x %02x %02x %02x %02x %02x %02x " ,
buf [ 0 ] , buf [ 1 ] , buf [ 2 ] , buf [ 3 ] , buf [ 4 ] , buf [ 5 ] , buf [ 6 ] , buf [ 7 ] ) ;
}
}
static int
k_send ( KodakAio_Scanner * s , void * buf , size_t buf_size , SANE_Status * status )
{
char fmt_buf [ 25 ] ;
kodakaio_com_str ( buf , fmt_buf ) ;
DBG ( 15 , " %s: size = %lu :%s \n " , __func__ , ( u_long ) buf_size , fmt_buf ) ;
if ( DBG_LEVEL > = 125 ) {
const unsigned char * s = buf ;
DBG ( 125 , " complete buffer: \n " ) ;
dump_hex_buffer_dense ( 125 , s , buf_size ) ;
}
if ( s - > hw - > connection = = SANE_KODAKAIO_NET ) {
return sanei_kodakaio_net_write_raw ( s , buf , buf_size , status ) ;
} else if ( s - > hw - > connection = = SANE_KODAKAIO_USB ) {
size_t n ;
n = buf_size ;
* status = sanei_usb_write_bulk ( s - > fd , buf , & n ) ;
DBG ( 50 , " USB: wrote %lu bytes, status: %s \n " , ( unsigned long ) n , sane_strstatus ( * status ) ) ;
return n ;
}
* status = SANE_STATUS_INVAL ;
return 0 ;
}
static ssize_t
k_recv ( KodakAio_Scanner * s , void * buf , ssize_t buf_size ,
SANE_Status * status )
{
/* requests and receives data this function makes the split between USB and NET
this function called by a number of others
In USB mode , this function will wait until data is available for a maximum of SCANNER_READ_TIMEOUT seconds .
2014-12-31 10:26:07 +00:00
In NET mode the timeout is in kodakaio_net_read
2012-07-01 01:28:14 +00:00
*/
ssize_t n = 0 ;
char fmt_buf [ 25 ] ;
time_t time_start ;
time_t time_now ;
struct timespec usb_delay , usb_rem ;
usb_delay . tv_sec = 0 ;
2012-12-23 21:23:43 +00:00
usb_delay . tv_nsec = 300000000 ; /* 0.3 sec */
2012-07-01 01:28:14 +00:00
if ( s - > hw - > connection = = SANE_KODAKAIO_NET ) {
time ( & time_start ) ;
2012-12-31 20:13:32 +00:00
DBG ( min ( 16 , DBG_READ ) , " [%ld] %s: net req size = %ld " , ( long ) time_start , __func__ , ( long ) buf_size ) ;
2012-07-01 01:28:14 +00:00
n = kodakaio_net_read ( s , buf , buf_size , status ) ;
2012-12-31 20:13:32 +00:00
DBG ( min ( 16 , DBG_READ ) , " returned %d \n " , n ) ;
2014-12-31 10:26:07 +00:00
if ( * status ! = SANE_STATUS_GOOD ) {
DBG ( 1 , " %s: err returned from kodakaio_net_read, %s \n " , __func__ , sane_strstatus ( * status ) ) ;
}
2012-07-01 01:28:14 +00:00
} else if ( s - > hw - > connection = = SANE_KODAKAIO_USB ) {
/* Start the clock for USB timeout */
time ( & time_start ) ;
/* Loop until we have data */
while ( n = = 0 ) {
n = buf_size ;
2012-12-23 21:23:43 +00:00
/* but what if the data is an exact number of blocks? */
2012-12-31 20:13:32 +00:00
DBG ( min ( 16 , DBG_READ ) , " [%ld] %s: usb req size = %ld " , ( long ) time_start , __func__ , ( long ) n ) ;
2012-07-01 01:28:14 +00:00
* status = sanei_usb_read_bulk ( s - > fd , ( SANE_Byte * ) buf , ( size_t * ) & n ) ;
2012-12-31 20:13:32 +00:00
DBG ( min ( 16 , DBG_READ ) , " returned %ld \n " , ( long ) n ) ;
2012-07-01 01:28:14 +00:00
if ( * status ! = SANE_STATUS_GOOD ) {
2012-12-31 20:13:32 +00:00
DBG ( min ( 16 , DBG_READ ) , " sanei_usb_read_bulk gave %s \n " , sane_strstatus ( * status ) ) ;
2012-07-01 01:28:14 +00:00
if ( * status = = SANE_STATUS_EOF ) {
2012-12-23 21:23:43 +00:00
/* If we have EOF status, wait for more data */
2012-07-01 01:28:14 +00:00
time ( & time_now ) ;
if ( difftime ( time_now , time_start ) < SCANNER_READ_TIMEOUT ) {
nanosleep ( & usb_delay , & usb_rem ) ;
}
else {
/* Timeout */
return n ;
}
}
else {
/* If we've encountered another type of error, return */
return n ;
}
}
}
}
if ( n = = 8 ) {
kodakaio_com_str ( buf , fmt_buf ) ;
2012-12-31 20:13:32 +00:00
DBG ( min ( 14 , DBG_READ ) , " %s: size = %ld, got %s \n " , __func__ , ( long int ) n , fmt_buf ) ;
2012-07-01 01:28:14 +00:00
}
/* dump buffer if appropriate */
if ( DBG_LEVEL > = 127 & & n > 0 ) {
const unsigned char * b = buf ;
dump_hex_buffer_dense ( 125 , b , buf_size ) ;
}
return n ;
}
static SANE_Status
kodakaio_expect_ack ( KodakAio_Scanner * s , unsigned char * rxbuf )
/* gets 8 byte reply, checks reply is an Ack and returns appropriate status */
{
SANE_Status status ;
k_recv ( s , rxbuf , 8 , & status ) ;
if ( status ! = SANE_STATUS_GOOD ) {
DBG ( 1 , " %s: rx err, %s \n " , __func__ , sane_strstatus ( status ) ) ;
return status ;
}
/* strncmp ignores diffent possible responses like escSS00000 and escSS02000 */
if ( strncmp ( ( char * ) KodakEsp_Ack , ( char * ) rxbuf , 4 ) ! = 0 ) {
2012-12-31 20:13:32 +00:00
DBG ( 1 , " No Ack received, Expected 0x%2x %2x %2x %2x... got 0x%2x %2x %2x %2x... \n " ,
2012-07-01 01:28:14 +00:00
KodakEsp_Ack [ 0 ] , KodakEsp_Ack [ 1 ] , KodakEsp_Ack [ 2 ] , KodakEsp_Ack [ 3 ] , rxbuf [ 0 ] , rxbuf [ 1 ] , rxbuf [ 2 ] , rxbuf [ 3 ] ) ;
return SANE_STATUS_IO_ERROR ;
}
return status ;
}
static SANE_Status
kodakaio_txrx ( KodakAio_Scanner * s , unsigned char * txbuf , unsigned char * rxbuf )
/* Sends 8 byte data to scanner and returns reply and appropriate status. */
{
SANE_Status status ;
2014-12-31 10:26:07 +00:00
ssize_t n = 0 ;
2012-07-01 01:28:14 +00:00
k_send ( s , txbuf , 8 , & status ) ;
if ( status ! = SANE_STATUS_GOOD ) {
DBG ( 1 , " %s: tx err, %s \n " , __func__ , sane_strstatus ( status ) ) ;
return status ;
}
2014-12-31 10:26:07 +00:00
n = k_recv ( s , rxbuf , 8 , & status ) ;
2012-07-01 01:28:14 +00:00
if ( status ! = SANE_STATUS_GOOD ) {
2012-12-31 20:13:32 +00:00
DBG ( 1 , " %s: %s gave rx err, %s \n " , __func__ , " txvalue " , sane_strstatus ( status ) ) ;
2012-07-01 01:28:14 +00:00
return status ;
}
2014-12-31 10:26:07 +00:00
if ( n = = 0 ) {
DBG ( 1 , " %s: try 1 k_recv returned 0 bytes with status %s \n " , __func__ , sane_strstatus ( status ) ) ;
n = k_recv ( s , rxbuf , 8 , & status ) ;
if ( status ! = SANE_STATUS_GOOD ) {
DBG ( 1 , " %s: %s gave rx err, %s \n " , __func__ , " txvalue " , sane_strstatus ( status ) ) ;
return status ;
}
if ( n = = 0 ) {
DBG ( 1 , " %s: try 2 k_recv returned 0 bytes with status %s \n " , __func__ , sane_strstatus ( status ) ) ;
return status ;
}
}
2012-07-01 01:28:14 +00:00
return status ;
}
static SANE_Status
kodakaio_txrxack ( KodakAio_Scanner * s , unsigned char * txbuf , unsigned char * rxbuf )
/*
Sends 8 byte data to scanner , gets 8 byte reply , checks reply is an Ack
and returns appropriate status
*/
{
SANE_Status status ;
k_send ( s , txbuf , 8 , & status ) ;
if ( status ! = SANE_STATUS_GOOD ) {
DBG ( 1 , " %s: tx err, %s \n " , __func__ , sane_strstatus ( status ) ) ;
return status ;
}
k_recv ( s , rxbuf , 8 , & status ) ;
if ( status ! = SANE_STATUS_GOOD ) {
2012-12-31 20:13:32 +00:00
DBG ( 1 , " %s: %s gave rx err, %s \n " , __func__ , " txvalue " , sane_strstatus ( status ) ) ;
2012-07-01 01:28:14 +00:00
return status ;
}
/* strncmp ignores different possible responses like escSS00000 and escSS02000 */
2012-12-31 20:13:32 +00:00
if ( strncmp ( ( char * ) KodakEsp_Ack , ( char * ) rxbuf , 3 ) = = 0 ) { /* was 4 byte comp */
2012-07-01 01:28:14 +00:00
if ( rxbuf [ 4 ] = = 0x01 & & s - > adf_loaded = = SANE_FALSE ) {
s - > adf_loaded = SANE_TRUE ;
2012-12-31 20:13:32 +00:00
DBG ( 5 , " %s: News - docs in ADF \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
}
2014-12-31 10:26:07 +00:00
else if ( rxbuf [ 4 ] ! =
0x01 & & s - > adf_loaded = = SANE_TRUE ) {
2012-07-01 01:28:14 +00:00
s - > adf_loaded = SANE_FALSE ;
2012-12-31 20:13:32 +00:00
DBG ( 5 , " %s: News - ADF is empty \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
}
}
else {
2012-12-31 20:13:32 +00:00
DBG ( 1 , " No Ack received, Sent 0x%2x %2x %2x %2x... got 0x%2x %2x %2x %2x... \n " ,
txbuf [ 0 ] , txbuf [ 1 ] , txbuf [ 2 ] , txbuf [ 3 ] , rxbuf [ 0 ] , rxbuf [ 1 ] , rxbuf [ 2 ] , rxbuf [ 3 ] ) ;
2012-07-01 01:28:14 +00:00
return SANE_STATUS_IO_ERROR ;
}
return status ;
}
2015-09-13 18:34:17 +00:00
/* unused function
2014-12-31 10:26:07 +00:00
static ssize_t
kodakaio_rxflush ( KodakAio_Scanner * s )
2015-09-13 18:34:17 +00:00
2014-12-31 10:26:07 +00:00
Tries to get 64 byte reply
and returns number of bytes read
2015-09-13 18:34:17 +00:00
2014-12-31 10:26:07 +00:00
{
SANE_Status status ;
unsigned char rxbuf [ 64 ] ;
ssize_t n = 0 ;
n = k_recv ( s , rxbuf , 64 , & status ) ;
if ( status ! = SANE_STATUS_GOOD ) {
DBG ( 1 , " %s: %s gave rx err, %s \n " , __func__ , " status " , sane_strstatus ( status ) ) ;
}
DBG ( 5 , " %s: flushed, %d bytes \n " , __func__ , ( int ) n ) ;
return n ;
}
2015-09-13 18:34:17 +00:00
*/
2014-12-31 10:26:07 +00:00
2012-12-23 21:23:43 +00:00
/*
* high - level communication commands
*/
2012-07-01 01:28:14 +00:00
2012-12-31 20:13:32 +00:00
static SANE_Status
k_hello ( KodakAio_Scanner * s )
{
SANE_Status status ;
unsigned char reply [ 8 ] ;
char fmt_buf [ 25 ] ;
DBG ( 5 , " %s \n " , __func__ ) ;
2014-12-31 10:26:07 +00:00
/* check that there is nothing already in the input buffer before starting
kodakaio_rxflush ( s ) ;
*/
/* preset the reply, so I can see if it gets changed */
reply [ 0 ] = 0 ; reply [ 1 ] = 1 ; reply [ 2 ] = 2 ; reply [ 3 ] = 3 ; reply [ 4 ] = 4 ; reply [ 5 ] = 5 ; reply [ 6 ] = 6 ; reply [ 7 ] = 7 ;
2012-12-31 20:13:32 +00:00
if ( ( status = kodakaio_txrx ( s , KodakEsp_V , reply ) ) ! = SANE_STATUS_GOOD ) {
DBG ( 1 , " %s: KodakEsp_V failure, %s \n " , __func__ , sane_strstatus ( status ) ) ;
return SANE_STATUS_IO_ERROR ;
}
if ( strncmp ( ( char * ) reply , ( char * ) KodakEsp_v , 3 ) ! = 0 ) {
kodakaio_com_str ( reply , fmt_buf ) ;
DBG ( 1 , " %s: KodakEsp_v err, got %s \n " , __func__ , fmt_buf ) ;
return SANE_STATUS_IO_ERROR ;
}
2014-12-31 10:26:07 +00:00
2012-12-31 20:13:32 +00:00
DBG ( 5 , " %s: OK %s \n " , __func__ , sane_strstatus ( status ) ) ;
return status ;
}
2012-07-01 01:28:14 +00:00
/* Start scan command */
static SANE_Status
cmd_start_scan ( SANE_Handle handle , size_t expect_total )
2012-12-31 20:13:32 +00:00
/* expect_total is the expected total no of bytes just for info -ve value not a problem? or is it for size_t? */
2012-07-01 01:28:14 +00:00
{
KodakAio_Scanner * s = ( KodakAio_Scanner * ) handle ;
SANE_Status status = SANE_STATUS_GOOD ;
unsigned char reply [ 8 ] ;
/*send the start command here */
2012-12-23 21:23:43 +00:00
print_status ( s , 5 ) ;
/*adf added 20/2/12, apparently an extra KodakEsp_F is sent when the adf is used */
if ( strcmp ( source_list [ s - > val [ OPT_SOURCE ] . w ] , ADF_STR ) = = 0 ) { /* adf is in use */
2012-07-01 01:28:14 +00:00
if ( ! s - > adf_loaded ) return SANE_STATUS_CANCELLED ; /* was SANE_STATUS_NO_DOCS; */
2012-12-23 21:23:43 +00:00
if ( kodakaio_txrxack ( s , KodakEsp_F , reply ) ! = SANE_STATUS_GOOD ) {
DBG ( 1 , " %s: Did not get a good reply to KodakEsp_F \n " , __func__ ) ;
return SANE_STATUS_IO_ERROR ;
}
2012-07-01 01:28:14 +00:00
}
2012-12-23 21:23:43 +00:00
if ( kodakaio_txrxack ( s , KodakEsp_E , reply ) ! = SANE_STATUS_GOOD ) {
DBG ( 1 , " %s: Did not get a good reply to KodakEsp_E \n " , __func__ ) ;
return SANE_STATUS_IO_ERROR ;
}
DBG ( 20 , " starting the scan, expected total bytes %d \n " , expect_total ) ;
2012-07-01 01:28:14 +00:00
k_send ( s , KodakEsp_Go , 8 , & status ) ;
if ( status ! = SANE_STATUS_GOOD )
2012-12-23 21:23:43 +00:00
DBG ( 1 , " %s: KodakEsp_Go command NOT successfully sent \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
else {
2012-12-23 21:23:43 +00:00
DBG ( 30 , " %s: KodakEsp_Go command successfully sent \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
s - > scanning = SANE_TRUE ;
}
return status ;
}
static SANE_Status
cmd_cancel_scan ( SANE_Handle handle )
{
KodakAio_Scanner * s = ( KodakAio_Scanner * ) handle ;
unsigned char reply [ 8 ] ;
2012-12-31 20:13:32 +00:00
/* adf added 20/2/12 should it be adf? or adf with paper in? */
2012-07-01 01:28:14 +00:00
if ( strcmp ( source_list [ s - > val [ OPT_SOURCE ] . w ] , ADF_STR ) = = 0 ) { /* adf */
2014-12-31 10:26:07 +00:00
if ( kodakaio_txrxack ( s , KodakEsp_F , reply ) ! = SANE_STATUS_GOOD )
{
DBG ( 1 , " %s: KodakEsp_F command failed \n " , __func__ ) ;
return SANE_STATUS_IO_ERROR ;
}
if ( kodakaio_txrxack ( s , KodakEsp_UnLock , reply ) ! = SANE_STATUS_GOOD )
{
DBG ( 1 , " %s: KodakEsp_UnLock command failed \n " , __func__ ) ;
return SANE_STATUS_IO_ERROR ;
}
2012-12-31 20:13:32 +00:00
DBG ( 5 , " %s unlocked the scanner with adf F U \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
}
2012-12-31 20:13:32 +00:00
else { /* no adf */
2014-12-31 10:26:07 +00:00
if ( kodakaio_txrxack ( s , KodakEsp_UnLock , reply ) ! = SANE_STATUS_GOOD )
{
DBG ( 1 , " %s: KodakEsp_UnLock command failed \n " , __func__ ) ;
return SANE_STATUS_IO_ERROR ;
}
2012-12-31 20:13:32 +00:00
DBG ( 5 , " %s unlocked the scanner U \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
}
s - > scanning = SANE_FALSE ;
return SANE_STATUS_GOOD ;
}
static SANE_Status
cmd_get_scanning_parameters ( SANE_Handle handle ,
SANE_Frame * format , SANE_Int * depth ,
SANE_Int * data_pixels , SANE_Int * pixels_per_line ,
SANE_Int * lines )
{
/* data_pixels is per line.
2012-12-31 20:13:32 +00:00
Old mc cmd read this stuff from the scanner . I don ' t think kodak can do that easily */
2012-12-23 21:23:43 +00:00
2012-07-01 01:28:14 +00:00
KodakAio_Scanner * s = ( KodakAio_Scanner * ) handle ;
SANE_Status status = SANE_STATUS_GOOD ;
NOT_USED ( format ) ;
NOT_USED ( depth ) ;
2012-12-23 21:23:43 +00:00
DBG ( 10 , " %s \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
2012-12-23 21:23:43 +00:00
/* Calculate returned values */
* lines = s - > params . lines ;
* pixels_per_line = s - > params . pixels_per_line ;
* data_pixels = s - > params . pixels_per_line ;
2012-07-01 01:28:14 +00:00
2012-12-23 21:23:43 +00:00
DBG ( 20 , " %s: data_pixels = %u, lines = %u, "
" pixels_per_line = %u) \n " , __func__ ,
* data_pixels , * lines , * pixels_per_line ) ;
2012-07-01 01:28:14 +00:00
return status ;
}
2014-09-13 22:26:04 +00:00
/* Set color curve command, low level, sends commands to the scanner*/
2012-07-01 01:28:14 +00:00
static SANE_Status
cmd_set_color_curve ( SANE_Handle handle , unsigned char col )
{
/* sends the color curve data for one color*/
KodakAio_Scanner * s = ( KodakAio_Scanner * ) handle ;
SANE_Status status = SANE_STATUS_GOOD ;
unsigned char tx_col [ 8 ] ;
unsigned char rx [ 8 ] ;
unsigned char tx_curve [ 256 ] ;
2014-09-07 12:38:58 +00:00
int i ; /* 7/9/14 was unsigned char and that stopped the loop that made the linear curve from going to 255 */
2012-07-01 01:28:14 +00:00
DBG ( 32 , " %s: start \n " , __func__ ) ;
tx_col [ 0 ] = 0x1b ; tx_col [ 1 ] = ' S ' ; tx_col [ 2 ] = ' K ' ; tx_col [ 3 ] = col ; tx_col [ 4 ] = 0 ; tx_col [ 5 ] = 0 ; tx_col [ 6 ] = 0 ; tx_col [ 7 ] = 0 ;
/* linear curve now but could send tailor made curves in future */
2014-09-07 12:38:58 +00:00
for ( i = 0 ; i < = 255 ; + + i ) tx_curve [ i ] = i ; /* 7/9/14 was i<255 the missing elements caused speckles */
2012-07-01 01:28:14 +00:00
k_send ( s , tx_col , 8 , & status ) ;
if ( status ! = SANE_STATUS_GOOD ) {
2012-12-23 21:23:43 +00:00
DBG ( 1 , " %s: tx err, %s \n " , __func__ , " curve command " ) ;
2012-07-01 01:28:14 +00:00
return status ;
}
k_send ( s , tx_curve , 256 , & status ) ;
if ( status ! = SANE_STATUS_GOOD ) {
2012-12-23 21:23:43 +00:00
DBG ( 1 , " %s: tx err, %s \n " , __func__ , " curve data " ) ;
2012-07-01 01:28:14 +00:00
return status ;
}
if ( kodakaio_expect_ack ( s , rx ) ! = SANE_STATUS_GOOD ) return SANE_STATUS_IO_ERROR ;
DBG ( 10 , " %s: sent curve OK, \n " , __func__ ) ;
return status ;
}
2014-09-13 22:26:04 +00:00
/* Set scanning parameters command, low level, sends commands to the scanner*/
2012-07-01 01:28:14 +00:00
static SANE_Status
cmd_set_scanning_parameters ( SANE_Handle handle ,
int resolution ,
int tl_x , int tl_y , int width , int height , unsigned char source )
/* NB. here int tl_x, int tl_y, int width, int height are in DPI units, not optres units! */
/* sends params to scanner, but should we store them too? */
{
KodakAio_Scanner * s = ( KodakAio_Scanner * ) handle ;
SANE_Status status = SANE_STATUS_GOOD ;
unsigned char tx_S [ 8 ] ;
unsigned char tx_dpi [ 8 ] ;
unsigned char tx_topleft [ 8 ] ;
unsigned char tx_widthheight [ 8 ] ;
unsigned char bufread [ 8 ] ;
int i ;
/*don't know the purpose of F yet. windows USB repeated 4 x why? does it affect the colour balance?*/
DBG ( 8 , " %s \n " , __func__ ) ;
for ( i = 0 ; i < 4 ; + + i ) {
kodakaio_txrxack ( s , KodakEsp_F , bufread ) ;
sleep ( 1 ) ;
}
/* kodakaio_txrxack(s, KodakEsp_F, bufread); for net, just once */
/* Source? bed /ADF */
tx_S [ 0 ] = 0x1b ; tx_S [ 1 ] = ' S ' ; tx_S [ 2 ] = ' S ' ; tx_S [ 3 ] = source ; tx_S [ 4 ] = 0 ; tx_S [ 5 ] = 0 ; tx_S [ 6 ] = 0 ; tx_S [ 7 ] = 0 ;
kodakaio_txrxack ( s , tx_S , bufread ) ;
/* Compression */
kodakaio_txrxack ( s , KodakEsp_Comp , bufread ) ;
/* DPI resolution */
tx_dpi [ 0 ] = 0x1b ;
tx_dpi [ 1 ] = ' S ' ;
tx_dpi [ 2 ] = ' D ' ;
tx_dpi [ 3 ] = resolution & 0xff ;
tx_dpi [ 4 ] = ( resolution > > 8 ) & 0xff ;
tx_dpi [ 5 ] = resolution & 0xff ;
tx_dpi [ 6 ] = ( resolution > > 8 ) & 0xff ;
tx_dpi [ 7 ] = 0 ;
kodakaio_txrxack ( s , tx_dpi , bufread ) ;
/* colour curves don't seem to be sent for usb preview
but it seems to do no harm to send them */
cmd_set_color_curve ( s , ' R ' ) ;
cmd_set_color_curve ( s , ' G ' ) ;
cmd_set_color_curve ( s , ' B ' ) ;
/* Origin top left s->tl_x and s->tl_y are in optres units
this command needs actual DPI units */
2012-12-23 21:23:43 +00:00
DBG ( 20 , " %s: left (DPI)=%d, top (DPI)=%d \n " , __func__ , tl_x , tl_y ) ;
2012-07-01 01:28:14 +00:00
tx_topleft [ 0 ] = 0x1b ;
tx_topleft [ 1 ] = ' S ' ;
tx_topleft [ 2 ] = ' O ' ;
tx_topleft [ 3 ] = ( tl_x ) & 0xff ;
tx_topleft [ 4 ] = ( ( tl_x ) > > 8 ) & 0xff ;
tx_topleft [ 5 ] = ( tl_y ) & 0xff ;
tx_topleft [ 6 ] = ( ( tl_y ) > > 8 ) & 0xff ;
tx_topleft [ 7 ] = 0 ;
kodakaio_txrxack ( s , tx_topleft , bufread ) ;
/* Z width height note the s->width and s->height are in optres units
this command needs actual DPI units */
tx_widthheight [ 0 ] = 0x1b ;
tx_widthheight [ 1 ] = ' S ' ;
tx_widthheight [ 2 ] = ' Z ' ;
tx_widthheight [ 3 ] = ( width ) & 0xff ;
tx_widthheight [ 4 ] = ( ( width ) > > 8 ) & 0xff ;
tx_widthheight [ 5 ] = ( height ) & 0xff ;
tx_widthheight [ 6 ] = ( ( height ) > > 8 ) & 0xff ;
tx_widthheight [ 7 ] = 0 ;
kodakaio_txrxack ( s , tx_widthheight , bufread ) ;
if ( status ! = SANE_STATUS_GOOD )
DBG ( 1 , " %s: Data NOT successfully sent \n " , __func__ ) ;
else
2012-12-23 21:23:43 +00:00
DBG ( 20 , " %s: Data successfully sent \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
return status ;
}
int
cmparray ( unsigned char * array1 , unsigned char * array2 , size_t len )
{
/* compares len bytes of the arrays returns 0 if they match
returns the first missmatch position if they don ' t match */
unsigned int i ;
for ( i = 0 ; i < len ; + + i )
{
if ( array1 [ i ] ! = array2 [ i ] ) return - 1 ;
}
return 0 ;
}
static SANE_Status
cmd_read_data ( SANE_Handle handle , unsigned char * buf , size_t * len )
{
/*
2012-12-23 21:23:43 +00:00
cmd_read_data is only used in k_read . It reads one block of data
read data using k_recv until you get the ackstring
2012-12-31 20:13:32 +00:00
when you get the ackstring return s - > ack and do padding if the padding option is selected
if no padding option return EOF
2012-07-01 01:28:14 +00:00
*/
KodakAio_Scanner * s = ( KodakAio_Scanner * ) handle ;
SANE_Status status ;
2012-08-09 15:33:41 +00:00
int oldtimeout = K_Request_Timeout ;
2012-07-01 01:28:14 +00:00
size_t bytecount ;
2012-12-31 20:13:32 +00:00
unsigned char * Last8 ; /* will point to the last 8 chars in buf */
2013-01-03 21:23:20 +00:00
int i , line , lines ;
2012-12-31 20:13:32 +00:00
2013-01-03 21:23:20 +00:00
if ( s - > ack & & s - > val [ OPT_PADDING ] . w ) {
2012-12-31 20:13:32 +00:00
/* do padding of whole block*/
2013-01-03 21:23:20 +00:00
/* memset(buf, 0x80, *len); need to work out the background colour for this */
lines = * len / s - > params . bytes_per_line ;
for ( line = 0 ; line < lines ; + + line ) {
for ( i = 0 ; i < s - > params . pixels_per_line ; + + i ) {
buf [ line * s - > params . bytes_per_line + i ] = s - > background [ 0 ] ; /*red */
buf [ line * s - > params . bytes_per_line + s - > params . pixels_per_line + i ] = s - > background [ 1 ] ; /*green */
buf [ line * s - > params . bytes_per_line + 2 * s - > params . pixels_per_line + i ] = s - > background [ 2 ] ; /*blue */
}
}
2012-12-31 20:13:32 +00:00
s - > bytes_unread - = * len ;
if ( s - > bytes_unread < 0 )
s - > bytes_unread = 0 ;
return SANE_STATUS_GOOD ;
}
2013-01-03 21:23:20 +00:00
if ( s - > ack & & ! s - > val [ OPT_PADDING ] . w ) {
2012-12-31 20:13:32 +00:00
s - > bytes_unread = 0 ;
s - > eof = SANE_TRUE ;
return SANE_STATUS_EOF ;
}
2012-07-01 01:28:14 +00:00
/* Temporarily set the poll timeout long instead of short,
2012-12-31 20:13:32 +00:00
* because a color scan needs > 5 seconds to initialize . Is this needed for kodak ? maybe */
2012-08-09 15:33:41 +00:00
K_Request_Timeout = K_Scan_Data_Timeout ;
sanei_usb_set_timeout ( K_Scan_Data_Timeout ) ;
2012-07-01 01:28:14 +00:00
bytecount = k_recv ( s , buf , * len , & status ) ;
2012-08-09 15:33:41 +00:00
K_Request_Timeout = oldtimeout ;
2012-07-01 01:28:14 +00:00
sanei_usb_set_timeout ( oldtimeout ) ;
2012-12-31 20:13:32 +00:00
/* We may need to do some special thing with the block request size to cope with usb blocks of any length
in order to keep the ack bytes , when using adf , at the end of one block ie not split between blocks .
But it seems that the scanner takes care of that , and gives you the ack as a separate 8 byte block */
if ( bytecount > = 8 ) {
/* it may be the last block from the scanner so look for Ack response in last 8 bytes */
Last8 = buf + bytecount - 8 ;
/* only compare 4 bytes because we sometimes get escSS02.. or escSS00..
is 4 the right number ? */
if ( cmparray ( Last8 , KodakEsp_Ack , 4 ) = = 0 ) {
DBG ( min ( 10 , DBG_READ ) , " %s: found KodakEsp_Ack at %d bytes of %d \n " , __func__ , bytecount , * len ) ;
s - > ack = SANE_TRUE ;
* len = bytecount - 8 ; /* discard the Ack response */
s - > bytes_unread - = * len ; /* return a short block */
}
else {
/* a not full buffer is returned usb does this */
DBG ( min ( 10 , DBG_READ ) , " %s: buffer not full, got %d bytes of %d \n " , __func__ , bytecount , * len ) ;
* len = bytecount ;
s - > bytes_unread - = bytecount ;
}
}
else {
2014-12-31 10:26:07 +00:00
DBG ( min ( 1 , DBG_READ ) , " %s: tiny read, got %d bytes of %d \n " , __func__ , ( int ) bytecount , * len ) ;
2012-12-31 20:13:32 +00:00
return SANE_STATUS_IO_ERROR ;
}
2013-01-03 21:23:20 +00:00
if ( * len > s - > params . bytes_per_line ) {
2014-09-13 22:26:04 +00:00
/* store average colour as background. That's not the ideal method but it's easy to implement. What's it used for? */
2013-01-03 21:23:20 +00:00
lines = * len / s - > params . bytes_per_line ;
s - > background [ 0 ] = 0 ;
s - > background [ 1 ] = 0 ;
s - > background [ 2 ] = 0 ;
for ( line = 0 ; line < lines ; + + line ) {
for ( i = 0 ; i < s - > params . pixels_per_line ; + + i ) {
s - > background [ 0 ] + = buf [ line * s - > params . bytes_per_line + i ] ; /*red */
s - > background [ 1 ] + = buf [ line * s - > params . bytes_per_line + s - > params . pixels_per_line + i ] ; /*green */
s - > background [ 2 ] + = buf [ line * s - > params . bytes_per_line + 2 * s - > params . pixels_per_line + i ] ; /*blue */
}
}
s - > background [ 0 ] = s - > background [ 0 ] / ( lines * s - > params . pixels_per_line ) ;
s - > background [ 1 ] = s - > background [ 1 ] / ( lines * s - > params . pixels_per_line ) ;
s - > background [ 2 ] = s - > background [ 2 ] / ( lines * s - > params . pixels_per_line ) ;
}
2012-12-31 20:13:32 +00:00
2012-07-01 01:28:14 +00:00
if ( status = = SANE_STATUS_GOOD )
2012-12-23 21:23:43 +00:00
if ( s - > bytes_unread < = 0 )
DBG ( min ( 2 , DBG_READ ) , " %s: Page fully read %d blocks, %ld bytes unread \n " , __func__ , s - > counter , ( long ) s - > bytes_unread ) ;
else
DBG ( min ( 20 , DBG_READ ) , " %s: Image data successfully read %ld bytes, %ld bytes unread \n " , __func__ , ( long ) bytecount , ( long ) s - > bytes_unread ) ;
2012-12-31 20:13:32 +00:00
else if ( s - > ack ) /* was (status == SANE_STATUS_EOF) */
DBG ( min ( 2 , DBG_READ ) , " %s: scanner data read ended %d blocks %ld bytes, %ld bytes unread \n " , __func__ , s - > counter , ( long ) bytecount , ( long ) s - > bytes_unread ) ;
2012-07-01 01:28:14 +00:00
else
2012-12-31 20:13:32 +00:00
DBG ( min ( 1 , DBG_READ ) , " %s: Image data read stopped with %s after %d blocks %ld bytes, %ld bytes unread \n " , __func__ , sane_strstatus ( status ) , s - > counter , ( long ) bytecount , ( long ) s - > bytes_unread ) ;
2012-07-01 01:28:14 +00:00
return status ;
}
/****************************************************************************
2012-11-28 21:35:36 +00:00
* kodakaio backend high - level operations * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-07-01 01:28:14 +00:00
static void
k_dev_init ( Kodak_Device * dev , const char * devname , int conntype )
{
DBG ( 5 , " %s for %s \n " , __func__ , devname ) ;
dev - > name = NULL ;
dev - > model = NULL ;
dev - > connection = conntype ;
dev - > sane . name = devname ;
dev - > sane . model = NULL ;
dev - > sane . type = " flatbed scanner " ;
dev - > sane . vendor = " Kodak " ;
dev - > cap = & kodakaio_cap [ CAP_DEFAULT ] ;
}
static SANE_Status
k_set_model ( KodakAio_Scanner * s , const char * model , size_t len )
{
unsigned char * buf ;
unsigned char * p ;
struct Kodak_Device * dev = s - > hw ;
if ( len < 1 ) return SANE_STATUS_INVAL ; /* to handle missing model */
buf = malloc ( len + 1 ) ;
if ( buf = = NULL )
return SANE_STATUS_NO_MEM ;
memcpy ( buf , model , len ) ;
buf [ len ] = ' \0 ' ;
p = & buf [ len - 1 ] ;
while ( * p = = ' ' ) {
* p = ' \0 ' ;
p - - ;
}
if ( dev - > model )
free ( dev - > model ) ;
dev - > model = strndup ( ( const char * ) buf , len ) ;
dev - > sane . model = dev - > model ;
DBG ( 10 , " %s: model is '%s' \n " , __func__ , dev - > model ) ;
free ( buf ) ;
return SANE_STATUS_GOOD ;
}
static void
k_set_device ( SANE_Handle handle , SANE_Word device )
{
KodakAio_Scanner * s = ( KodakAio_Scanner * ) handle ;
Kodak_Device * dev = s - > hw ;
int n ;
2012-12-23 21:23:43 +00:00
DBG ( 10 , " %s: 0x%x \n " , __func__ , device ) ;
2012-07-01 01:28:14 +00:00
for ( n = 0 ; n < NELEMS ( kodakaio_cap ) ; n + + ) {
if ( kodakaio_cap [ n ] . id = = device )
break ;
}
if ( n < NELEMS ( kodakaio_cap ) ) {
dev - > cap = & kodakaio_cap [ n ] ;
} else {
dev - > cap = & kodakaio_cap [ CAP_DEFAULT ] ;
DBG ( 1 , " unknown device 0x%x, using default %s \n " ,
device , dev - > cap - > model ) ;
}
k_set_model ( s , dev - > cap - > model , strlen ( dev - > cap - > model ) ) ;
}
static SANE_Status
k_discover_capabilities ( KodakAio_Scanner * s )
{
SANE_Status status = SANE_STATUS_GOOD ;
Kodak_Device * dev = s - > hw ;
SANE_String_Const * source_list_add = source_list ;
2012-12-23 21:23:43 +00:00
DBG ( 10 , " %s \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
/* always add flatbed */
* source_list_add + + = FBF_STR ;
/* TODO: How can I check for existence of an ADF??? */
if ( dev - > cap - > ADF = = SANE_TRUE ) {
* source_list_add + + = ADF_STR ;
2012-12-23 21:23:43 +00:00
DBG ( 10 , " %s: added adf to list \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
}
/* TODO: Is there any capability that we can extract from the
* device by some scanner command ? So far , it looks like
* the device does not support any reporting .
*/
dev - > x_range = & dev - > cap - > fbf_x_range ;
dev - > y_range = & dev - > cap - > fbf_y_range ;
2012-12-23 21:23:43 +00:00
DBG ( 10 , " x-range: %f %f \n " , SANE_UNFIX ( dev - > x_range - > min ) , SANE_UNFIX ( dev - > x_range - > max ) ) ;
DBG ( 10 , " y-range: %f %f \n " , SANE_UNFIX ( dev - > y_range - > min ) , SANE_UNFIX ( dev - > y_range - > max ) ) ;
2012-07-01 01:28:14 +00:00
DBG ( 5 , " End of %s, status:%s \n " , __func__ , sane_strstatus ( status ) ) ;
* source_list_add = NULL ; /* add end marker to source list */
return status ;
}
static SANE_Status
k_setup_block_mode ( KodakAio_Scanner * s )
{
2012-12-31 20:13:32 +00:00
/* works for USB and for net changing to make block size = a number of complete lines 28/12/12 */
s - > block_len = MAX_BLOCK_SIZE / s - > scan_bytes_per_line * s - > scan_bytes_per_line ;
2012-07-01 01:28:14 +00:00
s - > bytes_unread = s - > data_len ;
s - > counter = 0 ;
s - > bytes_read_in_line = 0 ;
if ( s - > line_buffer )
free ( s - > line_buffer ) ;
s - > line_buffer = malloc ( s - > scan_bytes_per_line ) ;
if ( s - > line_buffer = = NULL ) {
DBG ( 1 , " out of memory (line %d) \n " , __LINE__ ) ;
return SANE_STATUS_NO_MEM ;
}
2012-12-23 21:23:43 +00:00
DBG ( 10 , " %s: Setup block mode - scan_bytes_per_line=%d, pixels_per_line=%d, depth=%d, data_len=%d, block_len=%d, blocks=%d, last_len=%d \n " ,
2012-07-01 01:28:14 +00:00
__func__ , s - > scan_bytes_per_line , s - > params . pixels_per_line , s - > params . depth , s - > data_len , s - > block_len , s - > blocks , s - > last_len ) ;
return SANE_STATUS_GOOD ;
}
/* Call the commands to set scanning parameters
In the Kodak Aio the parameters are :
( x1b , " S " , " F " , 0 , 0 , 0 , 0 , 0 )
( x1b , " S " , " S " , 1 , 0 , 0 , 0 , 0 )
2012-12-31 20:13:32 +00:00
# It looks like the 4th param byte of the C command is compression 1=compress, 0=no compression
2012-07-01 01:28:14 +00:00
# 1st (or 3rd) param could be channels, 2nd could be bits per channel
2012-12-31 20:13:32 +00:00
( x1b , " S " , " C " , 3 , 8 , 3 , 0 , 0 ) # 3 , 8 , 3 , 1 , 0 ) was what the kodak software used with compression
2012-07-01 01:28:14 +00:00
( x1b , " S " , " D " , LowByte ( Res ) , HighByte ( Res ) , LowByte ( Res ) , HighByte ( Res ) , 0 ) # resolution in DPI
SendColour ( tcpCliSock , " R " )
SendColour ( tcpCliSock , " G " )
SendColour ( tcpCliSock , " B " )
( x1b , " S " , " O " , LowByte ( x0 * Res ) , HighByte ( x0 * Res ) , LowByte ( y0 * Res ) , HighByte ( y0 * Res ) , 0 ) # top left in pixels
( x1b , " S " , " Z " , LowByte ( x1 * Res ) , HighByte ( x1 * Res ) , LowByte ( y1 * Res ) , HighByte ( y1 * Res ) , 0 ) # bot right in pixels
( x1b , " S " , " E " , 1 , 0 , 0 , 0 , 0 )
*/
2012-12-23 21:23:43 +00:00
static SANE_Status
k_lock_scanner ( KodakAio_Scanner * s )
{
SANE_Status status ;
unsigned char reply [ 8 ] ;
2012-12-31 20:13:32 +00:00
status = k_hello ( s ) ;
if ( status ! = SANE_STATUS_GOOD ) {
DBG ( 1 , " %s k_hello failed with %s \n " , __func__ , sane_strstatus ( status ) ) ;
return status ;
}
2012-12-23 21:23:43 +00:00
2012-12-31 20:13:32 +00:00
if ( kodakaio_txrxack ( s , KodakEsp_Lock , reply ) ! = SANE_STATUS_GOOD ) {
DBG ( 1 , " %s Could not lock scanner \n " , __func__ ) ;
return SANE_STATUS_IO_ERROR ;
}
if ( s - > adf_loaded ) DBG ( 5 , " %s scanner locked, with docs in adf \n " , __func__ ) ;
else DBG ( 5 , " %s scanner locked, with no docs in adf \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
return SANE_STATUS_GOOD ;
}
static SANE_Status
k_set_scanning_parameters ( KodakAio_Scanner * s )
{
SANE_Status status ;
unsigned char rs , source ;
SANE_Int scan_pixels_per_line = 0 ;
int dpi , optres ;
dpi = s - > val [ OPT_RESOLUTION ] . w ;
optres = s - > hw - > cap - > optical_res ;
/* Find the resolution in the res list and assign the index (rs) */
for ( rs = 0 ; rs < s - > hw - > cap - > res_list_size ; rs + + ) {
if ( dpi = = s - > hw - > cap - > res_list [ rs ] )
break ;
}
/* ADF used? */
if ( strcmp ( source_list [ s - > val [ OPT_SOURCE ] . w ] , ADF_STR ) = = 0 ) {
source = 0x00 ;
} else {
source = 0x01 ;
}
/* TODO: Any way to set PREVIEW??? */
/* Remaining bytes unused */
status = cmd_set_scanning_parameters ( s , dpi ,
s - > left * dpi / optres , s - > top * dpi / optres , /* top/left start (dpi units)*/
s - > params . pixels_per_line , s - > params . lines , /* extent was s->width, s->height*/
source ) ; /* source */
if ( status ! = SANE_STATUS_GOOD )
DBG ( 1 , " %s: Command cmd_set_scanning_parameters failed, %s \n " ,
__func__ , sane_strstatus ( status ) ) ;
/* Now query the scanner for the current image parameters */
status = cmd_get_scanning_parameters ( s ,
& s - > params . format , & s - > params . depth ,
& scan_pixels_per_line ,
& s - > params . pixels_per_line , & s - > params . lines ) ;
if ( status ! = SANE_STATUS_GOOD ) {
DBG ( 1 , " %s: Command cmd_get_scanning_parameters failed, %s \n " ,
__func__ , sane_strstatus ( status ) ) ;
return status ;
}
/* Calculate how many bytes are really used per line */
s - > params . bytes_per_line = ceil ( s - > params . pixels_per_line * s - > params . depth / 8.0 ) ;
if ( s - > val [ OPT_MODE ] . w = = MODE_COLOR )
s - > params . bytes_per_line * = 3 ;
/* Calculate how many bytes per line will be returned by the scanner.
2014-09-13 22:26:04 +00:00
magicolor needed this because it uses padding so scan bytes per line ! = image bytes per line .
2012-07-01 01:28:14 +00:00
* The values needed for this are returned by get_scanning_parameters */
2014-09-13 22:26:04 +00:00
s - > scan_bytes_per_line = 3 * ceil ( scan_pixels_per_line ) ; /* we always scan in colour 8 bit */
2012-12-31 20:13:32 +00:00
s - > data_len = s - > scan_bytes_per_line * floor ( s - > height * dpi / optres + 0.5 ) ; /* NB this is the length for a full scan */
2014-12-31 10:26:07 +00:00
DBG ( 5 , " Check: scan_bytes_per_line = %d s->params.bytes_per_line = %d \n " , s - > scan_bytes_per_line , s - > params . bytes_per_line ) ;
2012-07-01 01:28:14 +00:00
/* k_setup_block_mode at the start of each page for adf to work */
status = k_setup_block_mode ( s ) ;
if ( status ! = SANE_STATUS_GOOD )
DBG ( 1 , " %s: Command k_setup_block_mode failed, %s \n " ,
__func__ , sane_strstatus ( status ) ) ;
DBG ( 18 , " %s: bytes_read_in_line: %d \n " , __func__ , s - > bytes_read_in_line ) ;
return status ;
}
static SANE_Status
k_check_adf ( KodakAio_Scanner * s )
{
/* 20/2/12 detect paper in the adf? acknowledge esc S S 00 01.. ?*/
if ( ! s - > adf_loaded ) {
DBG ( 5 , " %s: NO DOCS \n " , __func__ ) ;
return SANE_STATUS_NO_DOCS ;
}
else {
/* TODO: Check for jam in ADF */
DBG ( 5 , " %s: DOCS IN ADF \n " , __func__ ) ;
return SANE_STATUS_GOOD ;
}
}
static SANE_Status
k_scan_finish ( KodakAio_Scanner * s )
{
SANE_Status status = SANE_STATUS_GOOD ;
2012-12-23 21:23:43 +00:00
DBG ( 10 , " %s called \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
/* If we have not yet read all data, cancel the scan */
if ( s - > buf & & ! s - > eof )
status = cmd_cancel_scan ( s ) ;
if ( s - > line_buffer )
free ( s - > line_buffer ) ;
s - > line_buffer = NULL ;
free ( s - > buf ) ;
s - > buf = s - > end = s - > ptr = NULL ;
return status ;
}
static void
k_copy_image_data ( KodakAio_Scanner * s , SANE_Byte * data , SANE_Int max_length ,
SANE_Int * length )
/* copies the read data from s->line_buffer to the position in data pointer to by s->ptr
uncompressed data is RRRR . . . GGGG . . . BBBB per line */
{
2012-11-28 21:35:36 +00:00
SANE_Int bytes_available ;
2014-09-13 22:26:04 +00:00
SANE_Int threshold ;
2012-07-01 01:28:14 +00:00
DBG ( min ( 18 , DBG_READ ) , " %s: bytes_read in line: %d \n " , __func__ , s - > bytes_read_in_line ) ;
* length = 0 ;
2014-09-13 22:26:04 +00:00
threshold = 255 - ( int ) ( SANE_UNFIX ( s - > val [ OPT_THRESHOLD ] . w ) * 255.0 / 100.0 + 0.5 ) ; /* 255 - for the grey scale version */
DBG ( 20 , " %s: threshold: %d \n " , __func__ , threshold ) ;
2012-07-01 01:28:14 +00:00
while ( ( max_length > = s - > params . bytes_per_line ) & & ( s - > ptr < s - > end ) ) {
SANE_Int bytes_to_copy = s - > scan_bytes_per_line - s - > bytes_read_in_line ;
/* First, fill the line buffer for the current line: */
bytes_available = ( s - > end - s - > ptr ) ;
/* Don't copy more than we have buffer and available */
if ( bytes_to_copy > bytes_available )
bytes_to_copy = bytes_available ;
if ( bytes_to_copy > 0 ) {
memcpy ( s - > line_buffer + s - > bytes_read_in_line , s - > ptr , bytes_to_copy ) ;
s - > ptr + = bytes_to_copy ;
s - > bytes_read_in_line + = bytes_to_copy ;
}
/* We have filled as much as possible of the current line
* with data from the scanner . If we have a complete line ,
* copy it over .
line points to the current byte in the input s - > line_buffer
data points to the output buffer */
if ( ( s - > bytes_read_in_line > = s - > scan_bytes_per_line ) & &
( s - > params . bytes_per_line < = max_length ) )
{
SANE_Int i ;
SANE_Byte * line = s - > line_buffer ;
* length + = s - > params . bytes_per_line ;
for ( i = 0 ; i < s - > params . pixels_per_line ; + + i ) {
2014-09-13 22:26:04 +00:00
/* different behaviour for each mode */
2012-07-01 01:28:14 +00:00
if ( s - > val [ OPT_MODE ] . w = = MODE_COLOR ) {
2014-09-07 12:38:58 +00:00
/*interlace was subtracting from 255 until 6/9/14 */
2014-09-13 22:26:04 +00:00
* data + + = 255 - line [ 0 ] ; /*red */
* data + + = 255 - line [ s - > params . pixels_per_line ] ; /*green */
* data + + = 255 - line [ 2 * s - > params . pixels_per_line ] ; /*blue */
}
2012-07-01 01:28:14 +00:00
2014-12-19 22:52:48 +00:00
else if ( s - > val [ OPT_MODE ] . w = = MODE_LINEART ) { /* gives 1 bit output */
2014-09-13 22:26:04 +00:00
/*output image location*/
int offset = i % 8 ;
unsigned char mask = 0x80 > > offset ;
/*set if any colour is over the threshold */
if ( line [ 0 ] < threshold | | line [ s - > params . pixels_per_line ] < threshold | | line [ 2 * s - > params . pixels_per_line ] < threshold )
* data & = ~ mask ; /* white clear the bit in mask */
else
* data | = mask ; /* black set the bit in mask */
if ( offset = = 7 | | i = = s - > params . pixels_per_line - 1 )
data + + ; /* move on a byte if the byte is full or the line is complete */
2012-07-01 01:28:14 +00:00
}
2014-09-13 22:26:04 +00:00
else { /* greyscale - Average the 3 colours */
* data + + = ( 255 - line [ 0 ]
2012-07-01 01:28:14 +00:00
+ 255 - line [ s - > params . pixels_per_line ]
+ 255 - line [ 2 * s - > params . pixels_per_line ] )
/ 3 ;
}
2014-09-13 22:26:04 +00:00
line + + ;
2012-07-01 01:28:14 +00:00
}
/*debug file The same for color or grey because the scan is colour */
if ( RawScan ! = NULL ) {
for ( i = 0 ; i < s - > scan_bytes_per_line ; + + i ) fputc ( s - > line_buffer [ i ] , RawScan ) ;
}
max_length - = s - > params . bytes_per_line ;
s - > bytes_read_in_line - = s - > scan_bytes_per_line ;
}
}
}
static SANE_Status
k_init_parametersta ( KodakAio_Scanner * s )
{
int dpi , optres ;
/* struct mode_param *mparam; */
2012-12-23 21:23:43 +00:00
DBG ( 10 , " %s \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
memset ( & s - > params , 0 , sizeof ( SANE_Parameters ) ) ;
dpi = s - > val [ OPT_RESOLUTION ] . w ;
optres = s - > hw - > cap - > optical_res ;
/* mparam = &mode_params[s->val[OPT_MODE].w];does this get used? */
if ( SANE_UNFIX ( s - > val [ OPT_BR_Y ] . w ) = = 0 | |
SANE_UNFIX ( s - > val [ OPT_BR_X ] . w ) = = 0 )
return SANE_STATUS_INVAL ;
/* TODO: Use OPT_RESOLUTION or fixed 600dpi for left/top/width/height? */
s - > left = ( ( SANE_UNFIX ( s - > val [ OPT_TL_X ] . w ) / MM_PER_INCH ) * optres ) + 0.5 ;
s - > top = ( ( SANE_UNFIX ( s - > val [ OPT_TL_Y ] . w ) / MM_PER_INCH ) * optres ) + 0.5 ;
/* width in pixels */
s - > width =
( ( SANE_UNFIX ( s - > val [ OPT_BR_X ] . w -
s - > val [ OPT_TL_X ] . w ) / MM_PER_INCH ) * optres ) + 0.5 ;
2012-12-31 20:13:32 +00:00
s - > height = ( ( SANE_UNFIX ( s - > val [ OPT_BR_Y ] . w -
2012-07-01 01:28:14 +00:00
s - > val [ OPT_TL_Y ] . w ) / MM_PER_INCH ) * optres ) + 0.5 ;
2012-12-31 20:13:32 +00:00
2012-12-23 21:23:43 +00:00
DBG ( 20 , " %s: s->width = %d, s->height = %d optres units \n " ,
2012-07-01 01:28:14 +00:00
__func__ , s - > width , s - > height ) ;
s - > params . pixels_per_line = s - > width * dpi / optres + 0.5 ;
2012-12-31 20:13:32 +00:00
/* ADF used without padding? added 30/12/12 */
2013-01-03 21:23:20 +00:00
if ( strcmp ( source_list [ s - > val [ OPT_SOURCE ] . w ] , ADF_STR ) = = 0 & & ! s - > val [ OPT_PADDING ] . w )
2012-12-31 20:13:32 +00:00
s - > params . lines = - 1 ;
else
s - > params . lines = s - > height * dpi / optres + 0.5 ;
2012-07-01 01:28:14 +00:00
2012-12-23 21:23:43 +00:00
DBG ( 20 , " %s: resolution = %d, preview = %d \n " ,
2012-07-01 01:28:14 +00:00
__func__ , dpi , s - > val [ OPT_PREVIEW ] . w ) ;
2012-12-23 21:23:43 +00:00
DBG ( 20 , " %s: %p %p tlx %f tly %f brx %f bry %f [mm] \n " ,
2012-07-01 01:28:14 +00:00
__func__ , ( 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 ) ) ;
/*
2014-12-19 22:52:48 +00:00
* The default color depth is stored in mode_params . depth :
2012-07-01 01:28:14 +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 ;
}
2014-09-13 22:26:04 +00:00
DBG ( 20 , " %s: bit depth = s->params.depth = %d \n " , __func__ , s - > params . depth ) ;
2012-07-01 01:28:14 +00:00
s - > params . last_frame = SANE_TRUE ;
s - > params . bytes_per_line = 3 * ceil ( s - > params . depth * s - > params . pixels_per_line / 8.0 ) ;
2014-09-13 22:26:04 +00:00
/* kodak only scans in color and conversion to grey or lineart is done in the driver
2012-07-01 01:28:14 +00:00
s - > params . format = SANE_FRAME_RGB ; */
2014-09-13 22:26:04 +00:00
DBG ( 20 , " %s: s->val[OPT_MODE].w = %d (color is %d) \n " , __func__ , s - > val [ OPT_MODE ] . w , MODE_COLOR ) ;
2012-07-01 01:28:14 +00:00
if ( s - > val [ OPT_MODE ] . w = = MODE_COLOR ) s - > params . format = SANE_FRAME_RGB ;
2014-09-13 22:26:04 +00:00
else if ( s - > val [ OPT_MODE ] . w = = MODE_LINEART ) s - > params . format = SANE_FRAME_GRAY ;
2012-07-01 01:28:14 +00:00
else s - > params . format = SANE_FRAME_GRAY ;
2012-12-23 21:23:43 +00:00
DBG ( 20 , " %s: format=%d, bytes_per_line=%d, lines=%d \n " , __func__ , s - > params . format , s - > params . bytes_per_line , s - > params . lines ) ;
2012-12-31 20:13:32 +00:00
return ( s - > params . lines > = - 1 ) ? SANE_STATUS_GOOD : SANE_STATUS_INVAL ;
2012-07-01 01:28:14 +00:00
}
static SANE_Status
k_start_scan ( KodakAio_Scanner * s )
{
SANE_Status status ;
status = cmd_start_scan ( s , s - > data_len ) ;
if ( status ! = SANE_STATUS_GOOD ) {
DBG ( 1 , " %s: starting the scan failed (%s) \n " , __func__ , sane_strstatus ( status ) ) ;
}
return status ;
}
static SANE_Status
k_read ( struct KodakAio_Scanner * s )
{
2012-12-31 20:13:32 +00:00
unsigned char rx [ 8 ] ;
2012-07-01 01:28:14 +00:00
/* monitors progress of blocks and calls cmd_read_data to get each block
2012-12-31 20:13:32 +00:00
you don ' t know how many blocks there will be in advance because their size may be determined by the scanner */
2012-07-01 01:28:14 +00:00
SANE_Status status = SANE_STATUS_GOOD ;
size_t buf_len = 0 ;
2014-09-13 22:26:04 +00:00
/* have we passed everything we read to sane? */
2012-07-01 01:28:14 +00:00
if ( s - > ptr = = s - > end ) {
if ( s - > eof )
return SANE_STATUS_EOF ;
s - > counter + + ;
if ( s - > bytes_unread > = s - > block_len )
buf_len = s - > block_len ;
else
buf_len = s - > bytes_unread ;
2012-12-23 21:23:43 +00:00
DBG ( min ( 20 , DBG_READ ) , " %s: block %d, size %lu \n " , __func__ ,
2012-07-01 01:28:14 +00:00
s - > counter , ( unsigned long ) buf_len ) ;
/* receive image data + error code */
status = cmd_read_data ( s , s - > buf , & buf_len ) ;
if ( status ! = SANE_STATUS_GOOD & & status ! = SANE_STATUS_EOF ) { /* was just GOOD 20/2/12 */
DBG ( 1 , " %s: Receiving image data failed (%s) \n " ,
__func__ , sane_strstatus ( status ) ) ;
cmd_cancel_scan ( s ) ;
return status ;
}
2012-12-31 20:13:32 +00:00
DBG ( min ( 14 , DBG_READ ) , " %s: success %lu bytes of block %d, %d remain \n " , __func__ , ( unsigned long ) buf_len , s - > counter , s - > bytes_unread ) ;
2012-07-01 01:28:14 +00:00
if ( s - > bytes_unread > 0 ) {
if ( s - > canceling ) {
cmd_cancel_scan ( s ) ;
return SANE_STATUS_CANCELLED ;
}
2012-12-31 20:13:32 +00:00
if ( status = = SANE_STATUS_EOF ) {
/* page ended prematurely. */
}
2012-12-23 21:23:43 +00:00
}
else { /* s->bytes_unread <=0 This is the end of a page */
2012-07-01 01:28:14 +00:00
s - > eof = SANE_TRUE ;
2012-12-23 21:23:43 +00:00
DBG ( min ( 10 , DBG_READ ) , " %s: set EOF after %d blocks \n ============= \n " , __func__ , s - > counter ) ;
2012-12-31 20:13:32 +00:00
/* look for the terminating ack if required */
if ( ! s - > ack ) {
if ( kodakaio_expect_ack ( s , rx ) = = SANE_STATUS_GOOD ) {
s - > ack = SANE_TRUE ;
}
else {
DBG ( min ( 1 , DBG_READ ) , " %s: Did not get expected ack at end of page \n " , __func__ ) ;
return SANE_STATUS_IO_ERROR ;
}
}
2012-12-23 21:23:43 +00:00
}
2012-07-01 01:28:14 +00:00
s - > end = s - > buf + buf_len ;
s - > ptr = s - > buf ;
}
else {
2012-12-23 21:23:43 +00:00
DBG ( min ( 20 , DBG_READ ) , " %s: data left in buffer \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
}
return status ;
}
2012-12-23 21:23:43 +00:00
/*
* SANE API implementation ( high - level functions )
*/
2012-07-01 01:28:14 +00:00
static struct KodakaioCap *
2012-11-28 21:35:36 +00:00
get_device_from_identification ( const char * ident , const char * vid , const char * pid )
2012-07-01 01:28:14 +00:00
{
int n ;
2012-11-28 21:35:36 +00:00
SANE_Word pidnum , vidnum ;
if ( sscanf ( vid , " %x " , & vidnum ) = = EOF ) {
2012-12-23 21:23:43 +00:00
DBG ( 5 , " could not convert hex vid <%s> \n " , vid ) ;
2012-11-28 21:35:36 +00:00
return NULL ;
}
if ( sscanf ( pid , " %x " , & pidnum ) = = EOF ) {
2012-12-23 21:23:43 +00:00
DBG ( 5 , " could not convert hex pid <%s> \n " , pid ) ;
2012-11-28 21:35:36 +00:00
return NULL ;
}
2012-07-01 01:28:14 +00:00
for ( n = 0 ; n < NELEMS ( kodakaio_cap ) ; n + + ) {
if ( strcmp ( kodakaio_cap [ n ] . model , ident ) = = 0 ) {
2012-12-23 21:23:43 +00:00
DBG ( 20 , " matched <%s> & <%s> \n " , kodakaio_cap [ n ] . model , ident ) ;
2012-07-01 01:28:14 +00:00
return & kodakaio_cap [ n ] ;
}
2012-11-28 21:35:36 +00:00
else
if ( kodakaio_cap [ n ] . id = = pidnum & & 0x040A = = vidnum ) {
2012-12-23 21:23:43 +00:00
DBG ( 20 , " matched <%s> & <%s:%s> \n " , kodakaio_cap [ n ] . model , vid , pid ) ;
2012-11-28 21:35:36 +00:00
return & kodakaio_cap [ n ] ;
}
2012-07-01 01:28:14 +00:00
else {
2012-12-23 21:23:43 +00:00
DBG ( 20 , " not found <%s> & <%s> \n " , kodakaio_cap [ n ] . model , pid ) ;
2012-07-01 01:28:14 +00:00
}
}
return NULL ;
}
/*
* close_scanner ( )
*
* Close the open scanner . Depending on the connection method , a different
* close function is called .
*/
static void
close_scanner ( KodakAio_Scanner * s )
{
DBG ( 7 , " %s: fd = %d \n " , __func__ , s - > fd ) ;
if ( s - > fd = = - 1 )
return ;
k_scan_finish ( s ) ;
if ( s - > hw - > connection = = SANE_KODAKAIO_NET ) {
sanei_kodakaio_net_close ( s ) ;
sanei_tcp_close ( s - > fd ) ;
} else if ( s - > hw - > connection = = SANE_KODAKAIO_USB ) {
sanei_usb_close ( s - > fd ) ;
}
s - > fd = - 1 ;
}
static SANE_Bool
split_scanner_name ( const char * name , char * IP , unsigned int * model )
{
const char * device = name ;
const char * qm ;
* model = 0 ;
/* cut off leading net: */
if ( strncmp ( device , " net: " , 4 ) = = 0 )
device = & device [ 4 ] ;
qm = strchr ( device , ' ? ' ) ;
if ( qm ! = NULL ) {
size_t len = qm - device ;
strncpy ( IP , device , len ) ;
IP [ len ] = ' \0 ' ;
qm + + ;
if ( strncmp ( qm , " model= " , 6 ) = = 0 ) {
qm + = 6 ;
if ( ! sscanf ( qm , " 0x%x " , model ) )
sscanf ( qm , " %x " , model ) ;
}
} else {
strcpy ( IP , device ) ;
}
return SANE_TRUE ;
}
/*
* open_scanner ( )
*
* Open the scanner device . Depending on the connection method ,
* different open functions are called .
*/
static SANE_Status
open_scanner ( KodakAio_Scanner * s )
{
SANE_Status status = 0 ;
DBG ( 7 , " %s: %s \n " , __func__ , s - > hw - > sane . name ) ;
if ( s - > fd ! = - 1 ) {
2012-12-23 21:23:43 +00:00
DBG ( 10 , " scanner is already open: fd = %d \n " , s - > fd ) ;
2012-07-01 01:28:14 +00:00
return SANE_STATUS_GOOD ; /* no need to open the scanner */
}
if ( s - > hw - > connection = = SANE_KODAKAIO_NET ) {
/* device name has the form net:ipaddr?model=... */
char IP [ 1024 ] ;
unsigned int model = 0 ;
if ( ! split_scanner_name ( s - > hw - > sane . name , IP , & model ) )
return SANE_STATUS_INVAL ;
2012-12-23 21:23:43 +00:00
DBG ( 10 , " split_scanner_name OK model=0x%x \n " , model ) ;
2012-07-01 01:28:14 +00:00
/* normal with IP */
status = sanei_tcp_open ( IP , 9101 , & s - > fd ) ; /* (host,port,file pointer) */
if ( status ! = SANE_STATUS_GOOD ) DBG ( 1 , " Is network scanner switched on? \n " ) ;
if ( model > 0 )
k_set_device ( s , model ) ;
if ( status = = SANE_STATUS_GOOD ) {
status = sanei_kodakaio_net_open ( s ) ;
}
2012-12-23 21:23:43 +00:00
else DBG ( 1 , " status was not good at net open \n " ) ;
2012-07-01 01:28:14 +00:00
} else if ( s - > hw - > connection = = SANE_KODAKAIO_USB ) {
DBG ( 7 , " trying to open usb \n " ) ;
status = sanei_usb_open ( s - > hw - > sane . name , & s - > fd ) ;
if ( s - > hw - > cap - > out_ep > 0 )
sanei_usb_set_endpoint ( s - > fd ,
USB_DIR_OUT | USB_ENDPOINT_TYPE_BULK , s - > hw - > cap - > out_ep ) ;
if ( s - > hw - > cap - > in_ep > 0 )
sanei_usb_set_endpoint ( s - > fd ,
USB_DIR_IN | USB_ENDPOINT_TYPE_BULK , s - > hw - > cap - > in_ep ) ;
}
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 " ) ;
}
if ( status ! = SANE_STATUS_GOOD )
DBG ( 1 , " %s open failed: %s \n " , s - > hw - > sane . name ,
sane_strstatus ( status ) ) ;
else
DBG ( 3 , " scanner opened \n " ) ;
/* add check here of usb properties? */
/*sanei_usb_get_descriptor( SANE_Int dn, struct sanei_usb_dev_descriptor *desc );*/
return status ;
}
static SANE_Status
detect_usb ( struct KodakAio_Scanner * s )
{
SANE_Status status ;
SANE_Word 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 , " the device cannot be verified - will continue \n " ) ;
return SANE_STATUS_GOOD ;
}
/* check the vendor ID to see if we are dealing with a kodak device */
if ( vendor ! = SANE_KODAKAIO_VENDOR_ID ) {
/* this is not a supported vendor ID */
DBG ( 1 , " not a Kodak Aio device at %s (vendor id=0x%x) \n " ,
s - > hw - > sane . name , vendor ) ;
return SANE_STATUS_INVAL ;
}
numIds = kodakaio_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 == kodakaio_usb_product_ids[i]) */
if ( product = = kodakaio_cap [ i ] . id )
is_valid = SANE_TRUE ;
i + + ;
}
if ( is_valid = = SANE_FALSE ) {
DBG ( 1 , " the device at %s is not a supported (product id=0x%x) \n " ,
s - > hw - > sane . name , product ) ;
return SANE_STATUS_INVAL ;
}
2012-12-23 21:23:43 +00:00
DBG ( 2 , " found valid usb Kodak Aio scanner: 0x%x/0x%x (vendorID/productID) \n " ,
2012-07-01 01:28:14 +00:00
vendor , product ) ;
k_set_device ( s , product ) ; /* added 21/12/11 to try and get a name for the device */
return SANE_STATUS_GOOD ;
}
/*
* used by attach * and sane_get_devices
* a ptr to a single - linked list of Kodak_Device structs
* a ptr to a null term array of ptrs to SANE_Device structs
*/
static int num_devices ; /* number of scanners attached to backend */
static Kodak_Device * first_dev ; /* first scanner in list */
static const SANE_Device * * devlist = NULL ;
static struct KodakAio_Scanner *
scanner_create ( struct Kodak_Device * dev , SANE_Status * status )
{
struct KodakAio_Scanner * s ;
s = malloc ( sizeof ( struct KodakAio_Scanner ) ) ;
if ( s = = NULL ) {
* status = SANE_STATUS_NO_MEM ;
return NULL ;
}
memset ( s , 0x00 , sizeof ( struct KodakAio_Scanner ) ) ;
s - > fd = - 1 ;
s - > hw = dev ;
return s ;
}
static struct KodakAio_Scanner *
device_detect ( const char * name , int type , SANE_Status * status )
{
struct KodakAio_Scanner * s ;
struct Kodak_Device * dev ;
/* try to find the device in our list */
for ( dev = first_dev ; dev ; dev = dev - > next ) {
if ( strcmp ( dev - > sane . name , name ) = = 0 ) {
dev - > missing = 0 ;
DBG ( 10 , " %s: Device %s already attached! \n " , __func__ ,
name ) ;
return scanner_create ( dev , status ) ;
}
}
if ( type = = SANE_KODAKAIO_NODEV ) {
* status = SANE_STATUS_INVAL ;
return NULL ;
}
/* alloc and clear our device structure */
dev = malloc ( sizeof ( * dev ) ) ;
if ( ! dev ) {
* status = SANE_STATUS_NO_MEM ;
return NULL ;
}
memset ( dev , 0x00 , sizeof ( struct Kodak_Device ) ) ;
s = scanner_create ( dev , status ) ;
if ( s = = NULL )
return NULL ;
k_dev_init ( dev , name , type ) ;
* status = open_scanner ( s ) ;
if ( * status ! = SANE_STATUS_GOOD ) {
free ( s ) ;
free ( dev ) ;
return NULL ;
}
/* from now on, close_scanner() must be called */
/* USB requires special care */
if ( dev - > connection = = SANE_KODAKAIO_USB ) {
* status = detect_usb ( s ) ;
}
if ( * status ! = SANE_STATUS_GOOD )
goto close ;
/* set name and model (if not already set) */
if ( dev - > model = = NULL )
k_set_model ( s , " generic " , 7 ) ;
dev - > name = strdup ( name ) ;
dev - > sane . name = dev - > name ;
/* do we need to discover capabilities here? */
* status = k_discover_capabilities ( s ) ;
if ( * status ! = SANE_STATUS_GOOD )
goto close ;
if ( source_list [ 0 ] = = NULL | | dev - > cap - > dpi_range . min = = 0 ) {
DBG ( 1 , " something is wrong in the discovery process, aborting. \n " ) ;
* status = SANE_STATUS_IO_ERROR ;
goto close ;
}
/* add this scanner to the device list */
num_devices + + ;
dev - > missing = 0 ;
dev - > next = first_dev ;
first_dev = dev ;
return s ;
close :
close_scanner ( s ) ;
free ( dev ) ;
free ( s ) ;
return NULL ;
}
2012-11-28 21:35:36 +00:00
# if WITH_AVAHI
/* ProcessAvahiDevice is called to process each discovered device in turn */
2012-07-01 01:28:14 +00:00
void
2012-11-28 21:35:36 +00:00
ProcessAvahiDevice ( const char * device_id , const char * vid , const char * pid , const char * ip_addr )
2012-07-01 01:28:14 +00:00
{
struct KodakaioCap * cap ;
2012-11-28 21:35:36 +00:00
DBG ( min ( 10 , DBG_AUTO ) , " device_id = <%s> vid:pid = <%s:%s> \n " , device_id , vid , pid ) ;
2012-07-01 01:28:14 +00:00
2012-11-28 21:35:36 +00:00
/* check if it is a model likely to be supported: "KODAK ESP" or "KODAK HERO"
2012-07-01 01:28:14 +00:00
2012-11-28 21:35:36 +00:00
DBG ( min ( 10 , DBG_AUTO ) , " look up model <%s> \n " , device_model ) ; */
cap = get_device_from_identification ( " " , vid , pid ) ;
2012-07-01 01:28:14 +00:00
if ( cap = = NULL ) {
return ;
2012-11-28 21:35:36 +00:00
}
2012-07-01 01:28:14 +00:00
2012-12-23 21:23:43 +00:00
DBG ( min ( 10 , DBG_AUTO ) , " %s: Found autodiscovered device: %s (type 0x%x) \n " , __func__ , cap - > model , cap - > id ) ;
2012-11-28 21:35:36 +00:00
attach_one_net ( ip_addr , cap - > id ) ;
}
2012-07-01 01:28:14 +00:00
2012-11-28 21:35:36 +00:00
static void resolve_callback (
AvahiServiceResolver * r ,
AVAHI_GCC_UNUSED AvahiIfIndex interface ,
AVAHI_GCC_UNUSED AvahiProtocol protocol ,
AvahiResolverEvent event ,
const char * name ,
const char * type ,
const char * domain ,
const char * host_name ,
const AvahiAddress * address ,
uint16_t port ,
AvahiStringList * txt ,
AvahiLookupResultFlags flags ,
AVAHI_GCC_UNUSED void * userdata ) {
2013-10-14 21:22:53 +00:00
AvahiStringList * vid_pair_list = NULL , * pid_pair_list = NULL ;
2012-11-28 21:35:36 +00:00
char * pidkey , * pidvalue ;
char * vidkey , * vidvalue ;
size_t valuesize ;
NOT_USED ( flags ) ;
assert ( r ) ;
/* Called whenever a service has been resolved successfully or timed out */
switch ( event ) {
case AVAHI_RESOLVER_FAILURE :
DBG ( min ( 1 , DBG_AUTO ) , " (Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s \n " , name , type , domain , avahi_strerror ( avahi_client_errno ( avahi_service_resolver_get_client ( r ) ) ) ) ;
break ;
case AVAHI_RESOLVER_FOUND : {
char a [ AVAHI_ADDRESS_STR_MAX ] ;
avahi_address_snprint ( a , sizeof ( a ) , address ) ;
/* Output short for Kodak ESP */
2013-10-14 21:22:53 +00:00
DBG ( min ( 10 , DBG_AUTO ) , " %s:%u %s \n " , a , port , host_name ) ;
2012-11-28 21:35:36 +00:00
2013-10-14 21:22:53 +00:00
vid_pair_list = avahi_string_list_find ( txt , " vid " ) ;
if ( vid_pair_list ! = NULL ) {
avahi_string_list_get_pair ( vid_pair_list , & vidkey , & vidvalue , & valuesize ) ;
DBG ( min ( 10 , DBG_AUTO ) , " %s=%s " , vidkey , vidvalue ) ;
}
else DBG ( min ( 10 , DBG_AUTO ) , " failed to find key vid \n " ) ;
pid_pair_list = avahi_string_list_find ( txt , " pid " ) ;
if ( pid_pair_list ! = NULL ) {
avahi_string_list_get_pair ( pid_pair_list , & pidkey , & pidvalue , & valuesize ) ;
DBG ( min ( 10 , DBG_AUTO ) , " %s=%s \n " , pidkey , pidvalue ) ;
}
else DBG ( min ( 10 , DBG_AUTO ) , " failed to find key pid \n " ) ;
if ( pid_pair_list ! = NULL & & vid_pair_list ! = NULL ) {
2012-11-28 21:35:36 +00:00
ProcessAvahiDevice ( name , vidvalue , pidvalue , a ) ;
2013-10-14 21:22:53 +00:00
}
else DBG ( min ( 10 , DBG_AUTO ) , " didn't call ProcessAvahiDevice \n " ) ;
if ( vid_pair_list ! = NULL ) {
avahi_free ( vidkey ) ;
avahi_free ( vidvalue ) ;
DBG ( min ( 15 , DBG_AUTO ) , " vidkey and vidvalue freed \n " ) ;
}
if ( pid_pair_list ! = NULL ) {
avahi_free ( pidkey ) ;
avahi_free ( pidvalue ) ;
DBG ( min ( 15 , DBG_AUTO ) , " pidkey and pidvalue freed \n " ) ;
}
2012-11-28 21:35:36 +00:00
}
}
2013-10-14 21:22:53 +00:00
DBG ( min ( 10 , DBG_AUTO ) , " ending resolve_callback \n " ) ;
2012-11-28 21:35:36 +00:00
avahi_service_resolver_free ( r ) ;
}
static void browse_callback (
AvahiServiceBrowser * b ,
AvahiIfIndex interface ,
AvahiProtocol protocol ,
AvahiBrowserEvent event ,
const char * name ,
const char * type ,
const char * domain ,
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags ,
void * userdata ) {
AvahiClient * c = userdata ;
assert ( b ) ;
/* Called whenever a new services becomes available on the LAN or is removed from the LAN */
switch ( event ) {
case AVAHI_BROWSER_FAILURE :
DBG ( min ( 1 , DBG_AUTO ) , " (Browser) %s \n " , avahi_strerror ( avahi_client_errno ( avahi_service_browser_get_client ( b ) ) ) ) ;
avahi_simple_poll_quit ( simple_poll ) ;
return ;
case AVAHI_BROWSER_NEW :
2012-12-23 21:23:43 +00:00
DBG ( min ( 5 , DBG_AUTO ) , " (Browser) NEW: service '%s' of type '%s' in domain '%s' \n " , name , type , domain ) ;
2012-11-28 21:35:36 +00:00
/* We ignore the returned resolver object. In the callback
function we free it . If the server is terminated before
the callback function is called the server will free
the resolver for us . */
if ( ! ( avahi_service_resolver_new ( c , interface , protocol , name , type , domain , AVAHI_PROTO_UNSPEC , 0 , resolve_callback , c ) ) )
DBG ( min ( 1 , DBG_AUTO ) , " Failed to resolve service '%s': %s \n " , name , avahi_strerror ( avahi_client_errno ( c ) ) ) ;
break ;
case AVAHI_BROWSER_REMOVE :
DBG ( min ( 1 , DBG_AUTO ) , " (Browser) REMOVE: service '%s' of type '%s' in domain '%s' \n " , name , type , domain ) ;
break ;
case AVAHI_BROWSER_ALL_FOR_NOW :
case AVAHI_BROWSER_CACHE_EXHAUSTED :
2012-12-23 21:23:43 +00:00
DBG ( min ( 5 , DBG_AUTO ) , " (Browser) %s \n " , event = = AVAHI_BROWSER_CACHE_EXHAUSTED ? " CACHE_EXHAUSTED " : " ALL_FOR_NOW " ) ;
2012-11-28 21:35:36 +00:00
break ;
}
}
static void client_callback ( AvahiClient * c , AvahiClientState state , AVAHI_GCC_UNUSED void * userdata ) {
assert ( c ) ;
/* Called whenever the client or server state changes */
if ( state = = AVAHI_CLIENT_FAILURE ) {
DBG ( min ( 1 , DBG_AUTO ) , " Server connection failure: %s \n " , avahi_strerror ( avahi_client_errno ( c ) ) ) ;
avahi_simple_poll_quit ( simple_poll ) ;
}
2012-07-01 01:28:14 +00:00
}
static int
kodak_network_discovery ( const char * host )
/* If host = NULL do autodiscovery. If host != NULL try to verify the model
First version only does autodiscovery */
{
2012-11-28 21:35:36 +00:00
AvahiClient * client = NULL ;
AvahiServiceBrowser * sb = NULL ;
int error ;
int i , ret = 1 ;
2012-07-01 01:28:14 +00:00
NOT_USED ( host ) ;
2012-12-23 21:23:43 +00:00
DBG ( 2 , " %s: called \n " , __func__ ) ;
2012-11-28 21:35:36 +00:00
/* Allocate main loop object */
if ( ! ( simple_poll = avahi_simple_poll_new ( ) ) ) {
DBG ( min ( 1 , DBG_AUTO ) , " Failed to create simple poll object. \n " ) ;
goto fail ;
}
2012-07-01 01:28:14 +00:00
2012-11-28 21:35:36 +00:00
/* Allocate a new client */
client = avahi_client_new ( avahi_simple_poll_get ( simple_poll ) , 0 , client_callback , NULL , & error ) ;
/* Check wether creating the client object succeeded */
if ( ! client ) {
DBG ( min ( 1 , DBG_AUTO ) , " Failed to create client: %s \n " , avahi_strerror ( error ) ) ;
goto fail ;
}
/* Create the service browser */
if ( ! ( sb = avahi_service_browser_new ( client , AVAHI_IF_UNSPEC , AVAHI_PROTO_UNSPEC , " _scanner._tcp " , NULL , 0 , browse_callback , client ) ) ) {
DBG ( min ( 1 , DBG_AUTO ) , " Failed to create service browser: %s \n " , avahi_strerror ( avahi_client_errno ( client ) ) ) ;
goto fail ;
}
/* Run the main loop */
for ( i = 1 ; i < K_SNMP_Timeout / POLL_ITN_MS ; + + i ) {
avahi_simple_poll_iterate ( simple_poll , POLL_ITN_MS ) ;
}
ret = 0 ;
fail :
/* Cleanup things */
2012-12-23 21:23:43 +00:00
DBG ( min ( 10 , DBG_AUTO ) , " Cleaning up avahi. \n " ) ;
2012-11-28 21:35:36 +00:00
if ( sb )
avahi_service_browser_free ( sb ) ;
if ( client )
avahi_client_free ( client ) ;
if ( simple_poll )
avahi_simple_poll_free ( simple_poll ) ;
return ret ;
2012-07-01 01:28:14 +00:00
}
2012-11-28 21:35:36 +00:00
2012-07-01 01:28:14 +00:00
# endif
2012-11-28 21:35:36 +00:00
2012-07-01 01:28:14 +00:00
static SANE_Status
attach ( const char * name , int type )
{
SANE_Status status ;
KodakAio_Scanner * s ;
DBG ( 7 , " %s: devname = %s, type = %d \n " , __func__ , name , type ) ;
s = device_detect ( name , type , & status ) ;
if ( s = = NULL )
return status ;
close_scanner ( s ) ;
free ( s ) ;
return status ;
}
SANE_Status
attach_one_usb ( const char * dev )
{
DBG ( 7 , " %s: dev = %s \n " , __func__ , dev ) ;
return attach ( dev , SANE_KODAKAIO_USB ) ;
}
static SANE_Status
attach_one_net ( const char * dev , unsigned int model )
{
char name [ 1024 ] ;
DBG ( 7 , " %s: dev = %s \n " , __func__ , dev ) ;
if ( model > 0 ) {
snprintf ( name , 1024 , " net:%s?model=0x%x " , dev , model ) ;
} else {
snprintf ( name , 1024 , " net:%s " , dev ) ;
}
return attach ( name , SANE_KODAKAIO_NET ) ;
}
static SANE_Status
attach_one_config ( SANEI_Config __sane_unused__ * config , const char * line )
{
int vendor , product , timeout ;
int len = strlen ( line ) ;
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 */
int numIds = kodakaio_getNumberOfUSBProductIds ( ) ;
if ( vendor ! = SANE_KODAKAIO_VENDOR_ID ) {
DBG ( 7 , " Wrong vendor: numIds = %d, vendor = %d \n " , numIds , vendor ) ;
return SANE_STATUS_INVAL ; /* this is not a Kodak device */
}
/* kodakaio_usb_product_ids[numIds - 1] = product; */
kodakaio_cap [ numIds - 1 ] . id = product ;
sanei_usb_attach_matching_devices ( line , attach_one_usb ) ;
} else if ( strncmp ( line , " usb " , 3 ) = = 0 & & len = = 3 ) {
int i , numIds ;
2012-11-28 21:35:36 +00:00
/* auto detect ? */
2012-07-01 01:28:14 +00:00
numIds = kodakaio_getNumberOfUSBProductIds ( ) ;
for ( i = 0 ; i < numIds ; i + + ) {
/* sanei_usb_find_devices(SANE_KODAKAIO_VENDOR_ID,
kodakaio_usb_product_ids [ i ] , attach_one_usb ) ; */
sanei_usb_find_devices ( SANE_KODAKAIO_VENDOR_ID ,
kodakaio_cap [ i ] . id , attach_one_usb ) ;
}
} else if ( strncmp ( line , " net " , 3 ) = = 0 ) {
/* remove the "net" sub string */
const char * name = sanei_config_skip_whitespace ( line + 3 ) ;
char IP [ 1024 ] ;
unsigned int model = 0 ;
if ( strncmp ( name , " autodiscovery " , 13 ) = = 0 ) {
2012-11-28 21:35:36 +00:00
# if WITH_AVAHI
DBG ( 30 , " %s: Initiating network autodiscovery via avahi \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
kodak_network_discovery ( NULL ) ;
2012-11-28 21:35:36 +00:00
# else
2012-12-23 21:23:43 +00:00
DBG ( 20 , " %s: Network autodiscovery not done because not configured with avahi. \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
# endif
2012-11-28 21:35:36 +00:00
2012-07-01 01:28:14 +00:00
} else if ( sscanf ( name , " %s %x " , IP , & model ) = = 2 ) {
DBG ( 30 , " %s: Using network device on IP %s, forcing model 0x%x \n " , __func__ , IP , model ) ;
attach_one_net ( IP , model ) ;
} else {
2012-11-28 21:35:36 +00:00
DBG ( 1 , " %s: net entry %s may be a host name? \n " , __func__ , name ) ;
2012-07-01 01:28:14 +00:00
attach_one_net ( name , 0 ) ;
}
} else if ( sscanf ( line , " snmp-timeout %i \n " , & timeout ) ) {
2012-11-28 21:35:36 +00:00
/* Timeout for auto network discovery */
DBG ( 50 , " %s: network auto-discovery timeout set to %d \n " , __func__ , timeout ) ;
2012-08-09 15:33:41 +00:00
K_SNMP_Timeout = timeout ;
2012-07-01 01:28:14 +00:00
} else if ( sscanf ( line , " scan-data-timeout %i \n " , & timeout ) ) {
/* Timeout for scan data requests */
DBG ( 50 , " %s: Scan data timeout set to %d \n " , __func__ , timeout ) ;
2012-08-09 15:33:41 +00:00
K_Scan_Data_Timeout = timeout ;
2012-07-01 01:28:14 +00:00
} else if ( sscanf ( line , " request-timeout %i \n " , & timeout ) ) {
/* Timeout for all other read requests */
DBG ( 50 , " %s: Request timeout set to %d \n " , __func__ , timeout ) ;
2012-08-09 15:33:41 +00:00
K_Request_Timeout = timeout ;
2012-07-01 01:28:14 +00:00
} else {
/* TODO: Warning about unparsable line! */
}
return SANE_STATUS_GOOD ;
}
static void
free_devices ( void )
{
Kodak_Device * dev , * next ;
DBG ( 5 , " %s \n " , __func__ ) ;
for ( dev = first_dev ; dev ; dev = next ) {
next = dev - > next ;
free ( dev - > name ) ;
free ( dev - > model ) ;
free ( dev ) ;
}
if ( devlist )
free ( devlist ) ;
devlist = NULL ;
first_dev = NULL ;
}
SANE_Status
sane_init ( SANE_Int * version_code , SANE_Auth_Callback __sane_unused__ authorize )
{
DBG_INIT ( ) ;
DBG ( 1 , " ========================================== \n " ) ;
DBG ( 2 , " %s: " PACKAGE " " VERSION " \n " , __func__ ) ;
DBG ( 1 , " kodakaio backend, version %i.%i.%i \n " ,
KODAKAIO_VERSION , KODAKAIO_REVISION , KODAKAIO_BUILD ) ;
DBG ( 2 , " %s: called \n " , __func__ ) ;
if ( version_code ! = NULL )
* version_code = SANE_VERSION_CODE ( SANE_CURRENT_MAJOR , V_MINOR ,
KODAKAIO_BUILD ) ;
sanei_usb_init ( ) ;
2012-11-28 21:35:36 +00:00
# if WITH_AVAHI
2012-12-23 21:23:43 +00:00
DBG ( min ( 3 , DBG_AUTO ) , " avahi detected \n " ) ;
2012-11-28 21:35:36 +00:00
# else
2012-12-23 21:23:43 +00:00
DBG ( min ( 3 , DBG_AUTO ) , " avahi not detected \n " ) ;
2012-07-01 01:28:14 +00:00
# endif
return SANE_STATUS_GOOD ;
}
/* Clean up the list of attached scanners. */
void
sane_exit ( void )
{
DBG ( 5 , " %s \n " , __func__ ) ;
free_devices ( ) ;
}
SANE_Status
sane_get_devices ( const SANE_Device * * * device_list , SANE_Bool __sane_unused__ local_only )
{
Kodak_Device * dev , * s , * prev = 0 ;
int i ;
DBG ( 2 , " %s: called \n " , __func__ ) ;
sanei_usb_init ( ) ;
/* mark all existing scanners as missing, attach_one will remove mark */
for ( s = first_dev ; s ; s = s - > next ) {
s - > missing = 1 ;
}
/* Read the config, mark each device as found, possibly add new devs */
sanei_configure_attach ( KODAKAIO_CONFIG_FILE , NULL ,
attach_one_config ) ;
/*delete missing scanners from list*/
for ( s = first_dev ; s ; ) {
if ( s - > missing ) {
DBG ( 5 , " %s: missing scanner %s \n " , __func__ , s - > name ) ;
/*splice s out of list by changing pointer in prev to next*/
if ( prev ) {
prev - > next = s - > next ;
free ( s ) ;
s = prev - > next ;
num_devices - - ;
} else {
/*remove s from head of list */
first_dev = s - > next ;
free ( s ) ;
s = first_dev ;
prev = NULL ;
num_devices - - ;
}
} else {
prev = s ;
s = prev - > next ;
}
}
DBG ( 15 , " %s: found %d scanner(s) \n " , __func__ , num_devices ) ;
for ( s = first_dev ; s ; s = s - > next ) {
DBG ( 15 , " %s: found scanner %s \n " , __func__ , s - > name ) ;
}
if ( devlist )
free ( devlist ) ;
devlist = malloc ( ( num_devices + 1 ) * sizeof ( devlist [ 0 ] ) ) ;
if ( ! devlist ) {
DBG ( 1 , " out of memory (line %d) \n " , __LINE__ ) ;
return SANE_STATUS_NO_MEM ;
}
DBG ( 5 , " %s - results: \n " , __func__ ) ;
for ( i = 0 , dev = first_dev ; i < num_devices & & dev ; dev = dev - > next , i + + ) {
DBG ( 5 , " %d (%d): %s \n " , i , dev - > connection , dev - > model ) ;
devlist [ i ] = & dev - > sane ;
}
devlist [ i ] = NULL ;
if ( device_list ) {
* device_list = devlist ;
}
return SANE_STATUS_GOOD ;
}
static SANE_Status
init_options ( KodakAio_Scanner * s )
{
int i ;
SANE_Word * res_list ;
DBG ( 5 , " %s: called \n " , __func__ ) ;
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 ;
}
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 ;
/* "Scan Mode" group: */
s - > opt [ OPT_MODE_GROUP ] . name = SANE_NAME_STANDARD ;
s - > opt [ OPT_MODE_GROUP ] . title = SANE_TITLE_STANDARD ;
s - > opt [ OPT_MODE_GROUP ] . desc = SANE_DESC_STANDARD ;
s - > opt [ OPT_MODE_GROUP ] . type = SANE_TYPE_GROUP ;
s - > opt [ OPT_MODE_GROUP ] . cap = 0 ;
/* 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 ;
2014-12-19 22:52:48 +00:00
s - > val [ OPT_MODE ] . w = MODE_COLOR ; /* default */
DBG ( 20 , " %s: mode_list has first entry %s, default mode is %s \n " , __func__ , mode_list [ 0 ] , mode_list [ s - > val [ OPT_MODE ] . w ] ) ;
2012-07-01 01:28:14 +00:00
2014-09-13 22:26:04 +00:00
/* theshold the sane std says should be SANE_TYPE_FIXED 0..100 but all other backends seem to use INT 0..255 */
s - > opt [ OPT_THRESHOLD ] . name = SANE_NAME_THRESHOLD ;
s - > opt [ OPT_THRESHOLD ] . title = SANE_TITLE_THRESHOLD ;
s - > opt [ OPT_THRESHOLD ] . desc = SANE_DESC_THRESHOLD ;
s - > opt [ OPT_THRESHOLD ] . type = SANE_TYPE_FIXED ;
s - > opt [ OPT_THRESHOLD ] . unit = SANE_UNIT_PERCENT ;
s - > opt [ OPT_THRESHOLD ] . size = sizeof ( SANE_Word ) ;
s - > opt [ OPT_THRESHOLD ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_THRESHOLD ] . constraint . range = & percent_range_fixed ;
s - > val [ OPT_THRESHOLD ] . w = SANE_FIX ( 50.0 ) ;
DBG ( 20 , " %s: threshold initialised to fixed %f \n " , __func__ , SANE_UNFIX ( s - > val [ OPT_THRESHOLD ] . w ) ) ;
/* theshold the sane std says should be SANE_TYPE_FIXED 0..100 but all other backends seem to use INT 0..255
s - > opt [ OPT_THRESHOLD ] . name = SANE_NAME_THRESHOLD ;
s - > opt [ OPT_THRESHOLD ] . title = SANE_TITLE_THRESHOLD ;
s - > opt [ OPT_THRESHOLD ] . desc = SANE_DESC_THRESHOLD ;
s - > opt [ OPT_THRESHOLD ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_THRESHOLD ] . unit = SANE_UNIT_PERCENT ;
s - > opt [ OPT_THRESHOLD ] . size = sizeof ( SANE_Word ) ;
s - > opt [ OPT_THRESHOLD ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_THRESHOLD ] . constraint . range = & percent_range_int ;
s - > val [ OPT_THRESHOLD ] . w = 51 ;
DBG ( 20 , " %s: threshold initialised to int %d \n " , __func__ , s - > val [ OPT_THRESHOLD ] . w ) ; */
2012-07-01 01:28:14 +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 - > cap - > depth_list ;
s - > opt [ OPT_BIT_DEPTH ] . cap | = SANE_CAP_INACTIVE ;
s - > val [ OPT_BIT_DEPTH ] . w = s - > hw - > cap - > depth_list [ 1 ] ; /* the first "real" element is the default */
2012-12-31 20:13:32 +00:00
DBG ( 20 , " %s: depth list has depth_list[0] = %d entries \n " , __func__ , s - > hw - > cap - > depth_list [ 0 ] ) ;
2012-07-01 01:28:14 +00:00
if ( s - > hw - > cap - > depth_list [ 0 ] = = 1 ) { /* only one element in the list -> hide the option */
s - > opt [ OPT_BIT_DEPTH ] . cap | = SANE_CAP_INACTIVE ;
2012-12-31 20:13:32 +00:00
DBG ( 20 , " %s: Only one depth in list so inactive option \n " , __func__ ) ;
2012-07-01 01:28:14 +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 ;
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 ;
res_list = malloc ( ( s - > hw - > cap - > res_list_size + 1 ) * sizeof ( SANE_Word ) ) ;
if ( res_list = = NULL ) {
return SANE_STATUS_NO_MEM ;
}
* ( res_list ) = s - > hw - > cap - > res_list_size ;
memcpy ( & ( res_list [ 1 ] ) , s - > hw - > cap - > res_list , s - > hw - > cap - > res_list_size * sizeof ( SANE_Word ) ) ;
s - > opt [ OPT_RESOLUTION ] . constraint . word_list = res_list ;
s - > val [ OPT_RESOLUTION ] . w = s - > hw - > cap - > dpi_range . min ;
2014-09-13 22:26:04 +00:00
/* trial option for debugging
s - > opt [ OPT_TRIALOPT ] . name = " trialoption " ;
s - > opt [ OPT_TRIALOPT ] . title = " trialoption " ;
s - > opt [ OPT_TRIALOPT ] . desc = " trialoption " ;
s - > opt [ OPT_TRIALOPT ] . type = SANE_TYPE_INT ;
s - > opt [ OPT_TRIALOPT ] . unit = SANE_UNIT_NONE ;
s - > opt [ OPT_TRIALOPT ] . size = sizeof ( SANE_Word ) ;
s - > opt [ OPT_TRIALOPT ] . constraint_type = SANE_CONSTRAINT_RANGE ;
s - > opt [ OPT_TRIALOPT ] . constraint . range = & percent_range_int ;
s - > val [ OPT_TRIALOPT ] . w = 1 ; */
2012-07-01 01:28:14 +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 ;
s - > opt [ OPT_PREVIEW ] . type = SANE_TYPE_BOOL ;
s - > val [ OPT_PREVIEW ] . w = SANE_FALSE ;
for ( i = 0 ; source_list [ i ] ! = NULL ; + + i )
DBG ( 18 , " source_list: %s \n " , source_list [ i ] ) ;
/* 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 ;
s - > opt [ OPT_SOURCE ] . type = SANE_TYPE_STRING ;
s - > opt [ OPT_SOURCE ] . size = max_string_size ( source_list ) ;
s - > opt [ OPT_SOURCE ] . constraint_type = SANE_CONSTRAINT_STRING_LIST ;
s - > opt [ OPT_SOURCE ] . constraint . string_list = source_list ;
s - > val [ OPT_SOURCE ] . w = 0 ; /* always use Flatbed as default */
2012-12-31 20:13:32 +00:00
if ( ( ! s - > hw - > cap - > ADF ) ) {
DBG ( 9 , " device with no adf detected source option inactive \n " ) ;
s - > opt [ OPT_SOURCE ] . cap | = SANE_CAP_INACTIVE ;
}
2012-07-01 01:28:14 +00:00
2013-01-03 21:23:20 +00:00
/* Are there any ESP scanners that are duplex? */
2012-07-01 01:28:14 +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 */
2013-01-03 21:23:20 +00:00
if ( ( ! s - > hw - > cap - > ADF ) | | ( ! s - > hw - > cap - > adf_duplex ) )
2012-07-01 01:28:14 +00:00
s - > opt [ OPT_ADF_MODE ] . cap | = SANE_CAP_INACTIVE ;
/* "Geometry" group: */
s - > opt [ OPT_GEOMETRY_GROUP ] . name = SANE_NAME_GEOMETRY ;
s - > opt [ OPT_GEOMETRY_GROUP ] . title = SANE_TITLE_GEOMETRY ;
s - > opt [ OPT_GEOMETRY_GROUP ] . desc = SANE_DESC_GEOMETRY ;
s - > opt [ OPT_GEOMETRY_GROUP ] . type = SANE_TYPE_GROUP ;
s - > opt [ OPT_GEOMETRY_GROUP ] . cap = SANE_CAP_ADVANCED ;
/* 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 ;
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 ;
/* 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 ;
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 ;
/* 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 ;
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 ;
/* 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 ;
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 ;
2013-01-03 21:23:20 +00:00
/* padding short pages in adf */
s - > opt [ OPT_PADDING ] . name = " adf-padding " ;
s - > opt [ OPT_PADDING ] . title = " pad short adf pages " ;
s - > opt [ OPT_PADDING ] . desc = " Selects whether to make short pages up to full length " ;
s - > opt [ OPT_PADDING ] . type = SANE_TYPE_BOOL ;
s - > val [ OPT_PADDING ] . w = SANE_FALSE ;
if ( ( ! s - > hw - > cap - > ADF ) | | ( strcmp ( source_list [ s - > val [ OPT_SOURCE ] . w ] , ADF_STR ) ! = 0 ) )
{
DBG ( 9 , " adf not source so padding option off and inactive \n " ) ;
s - > opt [ OPT_PADDING ] . cap | = SANE_CAP_INACTIVE ;
}
2012-07-01 01:28:14 +00:00
return SANE_STATUS_GOOD ;
}
SANE_Status
sane_open ( SANE_String_Const name , SANE_Handle * handle )
{
SANE_Status status ;
KodakAio_Scanner * s = NULL ;
int l = strlen ( name ) ;
DBG ( 2 , " %s: name = %s \n " , __func__ , name ) ;
/* probe if empty device name provided */
if ( l = = 0 ) {
status = sane_get_devices ( NULL , 0 ) ;
if ( status ! = SANE_STATUS_GOOD ) {
return status ;
}
if ( first_dev = = NULL ) {
DBG ( 1 , " no device detected \n " ) ;
return SANE_STATUS_INVAL ;
}
s = device_detect ( first_dev - > sane . name , first_dev - > connection ,
& status ) ;
if ( s = = NULL ) {
DBG ( 1 , " cannot open a perfectly valid device (%s), "
" please report to the authors \n " , name ) ;
return SANE_STATUS_INVAL ;
}
} else {
if ( strncmp ( name , " net: " , 4 ) = = 0 ) {
s = device_detect ( name , SANE_KODAKAIO_NET , & status ) ;
if ( s = = NULL )
return status ;
} else if ( strncmp ( name , " libusb: " , 7 ) = = 0 ) {
s = device_detect ( name , SANE_KODAKAIO_USB , & status ) ;
if ( s = = NULL )
return status ;
} else {
/* as a last resort, check for a match
* in the device list . This should handle platforms without libusb .
*/
if ( first_dev = = NULL ) {
status = sane_get_devices ( NULL , 0 ) ;
if ( status ! = SANE_STATUS_GOOD ) {
return status ;
}
}
s = device_detect ( name , SANE_KODAKAIO_NODEV , & status ) ;
if ( s = = NULL ) {
DBG ( 1 , " invalid device name: %s \n " , name ) ;
return SANE_STATUS_INVAL ;
}
}
}
/* s is always valid here */
DBG ( 10 , " handle obtained \n " ) ;
status = k_discover_capabilities ( s ) ; /* added 27/12/11 to fix source list problem
maybe we should only be rebuilding the source list here ? */
if ( status ! = SANE_STATUS_GOOD )
return status ;
init_options ( s ) ;
* handle = ( SANE_Handle ) s ;
2014-12-31 10:26:07 +00:00
/* moving the open scanner section below to sane_start 27/12/14
2012-07-01 01:28:14 +00:00
status = open_scanner ( s ) ;
if ( status ! = SANE_STATUS_GOOD ) {
free ( s ) ;
return status ;
}
2014-12-31 10:26:07 +00:00
*/
2012-07-01 01:28:14 +00:00
return status ;
}
void
sane_close ( SANE_Handle handle )
{
KodakAio_Scanner * s ;
/*
* XXX Test if there is still data pending from
* the scanner . If so , then do a cancel
*/
s = ( KodakAio_Scanner * ) handle ;
DBG ( 2 , " %s: called \n " , __func__ ) ;
2014-12-31 10:26:07 +00:00
/* moving the close scanner section below to sane_cancel 27/12/14 */
2012-07-01 01:28:14 +00:00
if ( s - > fd ! = - 1 )
close_scanner ( s ) ;
2014-12-31 10:26:07 +00:00
/* end of section */
2012-07-01 01:28:14 +00:00
if ( RawScan ! = NULL )
fclose ( RawScan ) ;
RawScan = NULL ;
free ( s ) ;
}
const SANE_Option_Descriptor *
sane_get_option_descriptor ( SANE_Handle handle , SANE_Int option )
{
2012-12-31 20:13:32 +00:00
/* this may be a sane call, but it happens way too often to have DBG level 2 */
2012-07-01 01:28:14 +00:00
KodakAio_Scanner * s = ( KodakAio_Scanner * ) handle ;
2014-09-13 22:26:04 +00:00
DBG ( 30 , " %s: called for option %d \n " , __func__ , option ) ;
2012-12-31 20:13:32 +00:00
2012-07-01 01:28:14 +00:00
if ( option < 0 | | option > = NUM_OPTIONS )
return NULL ;
return s - > opt + option ;
}
static const SANE_String_Const *
search_string_list ( const SANE_String_Const * list , SANE_String value )
{
while ( * list ! = NULL & & strcmp ( value , * list ) ! = 0 )
list + + ;
return ( ( * list = = NULL ) ? NULL : list ) ;
}
/*
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 .
*/
static void
activateOption ( KodakAio_Scanner * s , SANE_Int option , SANE_Bool * change )
{
if ( ! SANE_OPTION_IS_ACTIVE ( s - > opt [ option ] . cap ) ) {
s - > opt [ option ] . cap & = ~ SANE_CAP_INACTIVE ;
* change = SANE_TRUE ;
}
}
static void
deactivateOption ( KodakAio_Scanner * s , SANE_Int option , SANE_Bool * change )
{
if ( SANE_OPTION_IS_ACTIVE ( s - > opt [ option ] . cap ) ) {
s - > opt [ option ] . cap | = SANE_CAP_INACTIVE ;
* change = SANE_TRUE ;
}
}
static SANE_Status
getvalue ( SANE_Handle handle , SANE_Int option , void * value )
{
KodakAio_Scanner * s = ( KodakAio_Scanner * ) handle ;
SANE_Option_Descriptor * sopt = & ( s - > opt [ option ] ) ;
Option_Value * sval = & ( s - > val [ option ] ) ;
DBG ( 17 , " %s: option = %d \n " , __func__ , option ) ;
switch ( option ) {
case OPT_NUM_OPTS :
case OPT_BIT_DEPTH :
2014-09-13 22:26:04 +00:00
/* case OPT_TRIALOPT: */
2012-07-01 01:28:14 +00:00
case OPT_RESOLUTION :
case OPT_PREVIEW :
case OPT_TL_X :
case OPT_TL_Y :
case OPT_BR_X :
case OPT_BR_Y :
* ( ( SANE_Word * ) value ) = sval - > w ;
2014-09-13 22:26:04 +00:00
DBG ( 20 , " %s: got option %d as %d \n " , __func__ , option , * ( ( SANE_Word * ) value ) ) ;
break ;
case OPT_THRESHOLD :
* ( ( SANE_Word * ) value ) = sval - > w ;
DBG ( 20 , " %s: got option %d as %f \n " , __func__ , option , SANE_UNFIX ( * ( ( SANE_Word * ) value ) ) ) ;
/*DBG(20, "%s: got option %d as %d\n", __func__, option, *((SANE_Word *) value));*/
2012-07-01 01:28:14 +00:00
break ;
case OPT_MODE :
case OPT_SOURCE :
case OPT_ADF_MODE :
strcpy ( ( char * ) value , sopt - > constraint . string_list [ sval - > w ] ) ;
break ;
2013-01-03 21:23:20 +00:00
case OPT_PADDING :
* ( ( SANE_Bool * ) value ) = sval - > w ;
break ;
2012-07-01 01:28:14 +00:00
default :
2014-09-13 22:26:04 +00:00
DBG ( 20 , " %s: returning inval \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
return SANE_STATUS_INVAL ;
}
2014-09-13 22:26:04 +00:00
DBG ( 20 , " %s: returning good \n " , __func__ ) ;
2012-07-01 01:28:14 +00:00
return SANE_STATUS_GOOD ;
}
/*
* Handles setting the source ( flatbed , or auto document feeder ( ADF ) ) .
*
*/
static void
change_source ( KodakAio_Scanner * s , SANE_Int optindex , char * value )
{
int force_max = SANE_FALSE ;
SANE_Bool dummy ;
DBG ( 5 , " %s: optindex = %d, source = '%s' \n " , __func__ , optindex ,
value ) ;
if ( s - > val [ OPT_SOURCE ] . w = = optindex )
return ;
s - > val [ OPT_SOURCE ] . w = optindex ;
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 ;
}
if ( strcmp ( ADF_STR , value ) = = 0 ) {
s - > hw - > x_range = & s - > hw - > cap - > adf_x_range ;
s - > hw - > y_range = & s - > hw - > cap - > adf_y_range ;
if ( s - > hw - > cap - > adf_duplex ) {
activateOption ( s , OPT_ADF_MODE , & dummy ) ;
} else {
deactivateOption ( s , OPT_ADF_MODE , & dummy ) ;
s - > val [ OPT_ADF_MODE ] . w = 0 ;
}
2013-01-03 21:23:20 +00:00
activateOption ( s , OPT_PADDING , & dummy ) ;
2012-07-01 01:28:14 +00:00
2012-12-23 21:23:43 +00:00
DBG ( 5 , " adf activated flag = %d \n " , s - > hw - > cap - > adf_duplex ) ;
2012-07-01 01:28:14 +00:00
} else {
/* ADF not active */
s - > hw - > x_range = & s - > hw - > cap - > fbf_x_range ;
s - > hw - > y_range = & s - > hw - > cap - > fbf_y_range ;
deactivateOption ( s , OPT_ADF_MODE , & dummy ) ;
2013-01-03 21:23:20 +00:00
deactivateOption ( s , OPT_PADDING , & dummy ) ;
2012-07-01 01:28:14 +00:00
}
s - > opt [ OPT_BR_X ] . constraint . range = s - > hw - > x_range ;
s - > opt [ OPT_BR_Y ] . constraint . range = s - > hw - > y_range ;
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 ;
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 ;
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 ;
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 ;
}
static SANE_Status
setvalue ( SANE_Handle handle , SANE_Int option , void * value , SANE_Int * info )
{
KodakAio_Scanner * s = ( KodakAio_Scanner * ) handle ;
SANE_Option_Descriptor * sopt = & ( s - > opt [ option ] ) ;
Option_Value * sval = & ( s - > val [ option ] ) ;
SANE_Status status ;
const SANE_String_Const * optval = NULL ;
int optindex = 0 ;
SANE_Bool reload = SANE_FALSE ;
DBG ( 17 , " %s: option = %d, value = %p, as word: %d \n " , __func__ , option , value , * ( SANE_Word * ) value ) ;
status = sanei_constrain_value ( sopt , value , info ) ;
if ( status ! = SANE_STATUS_GOOD )
return status ;
if ( info & & value & & ( * info & SANE_INFO_INEXACT )
& & sopt - > type = = SANE_TYPE_INT )
DBG ( 17 , " %s: constrained val = %d \n " , __func__ ,
* ( SANE_Word * ) value ) ;
if ( sopt - > constraint_type = = SANE_CONSTRAINT_STRING_LIST ) {
optval = search_string_list ( sopt - > constraint . string_list ,
( char * ) value ) ;
if ( optval = = NULL )
return SANE_STATUS_INVAL ;
optindex = optval - sopt - > constraint . string_list ;
}
switch ( option ) {
case OPT_MODE :
{
sval - > w = optindex ;
2014-09-13 22:26:04 +00:00
/* if binary, then disable the bit depth selection and enable threshold */
2014-12-19 22:52:48 +00:00
if ( optindex = = MODE_LINEART ) {
2014-09-13 22:26:04 +00:00
DBG ( 17 , " %s: binary mode setting depth to 1 \n " , __func__ ) ;
s - > val [ OPT_BIT_DEPTH ] . w = 1 ;
2012-07-01 01:28:14 +00:00
s - > opt [ OPT_BIT_DEPTH ] . cap | = SANE_CAP_INACTIVE ;
2014-09-13 22:26:04 +00:00
s - > opt [ OPT_THRESHOLD ] . cap & = ~ SANE_CAP_INACTIVE ;
2012-07-01 01:28:14 +00:00
} else {
2014-09-13 22:26:04 +00:00
if ( s - > hw - > cap - > depth_list [ 0 ] = = 1 ) { /* only one entry in the list ? */
DBG ( 17 , " %s: non-binary mode but only one depth available \n " , __func__ ) ;
s - > val [ OPT_BIT_DEPTH ] . w = s - > hw - > cap - > depth_list [ 1 ] ;
s - > opt [ OPT_BIT_DEPTH ] . cap | = SANE_CAP_INACTIVE ;
s - > opt [ OPT_THRESHOLD ] . cap | = SANE_CAP_INACTIVE ;
} else { /* there is a list to choose from ? */
DBG ( 17 , " %s: non-binary mode and depth list available \n " , __func__ ) ;
s - > opt [ OPT_BIT_DEPTH ] . cap & = ~ SANE_CAP_INACTIVE ;
s - > val [ OPT_BIT_DEPTH ] . w = mode_params [ optindex ] . depth ;
s - > opt [ OPT_THRESHOLD ] . cap | = SANE_CAP_INACTIVE ; /* does not work in xsane ? */
2012-07-01 01:28:14 +00:00
}
}
reload = SANE_TRUE ;
break ;
}
case OPT_BIT_DEPTH :
sval - > w = * ( ( SANE_Word * ) value ) ;
mode_params [ s - > val [ OPT_MODE ] . w ] . depth = sval - > w ;
reload = SANE_TRUE ;
break ;
2014-09-13 22:26:04 +00:00
case OPT_THRESHOLD :
sval - > w = * ( ( SANE_Word * ) value ) ;
DBG ( 17 , " setting threshold to %f \n " , SANE_UNFIX ( sval - > w ) ) ;
/*DBG(17, "setting threshold to %d\n", sval->w);*/
/*reload = SANE_TRUE; what does this do?*/
break ;
2012-07-01 01:28:14 +00:00
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 ;
case OPT_SOURCE :
change_source ( s , optindex , ( char * ) value ) ;
reload = SANE_TRUE ;
break ;
case OPT_ADF_MODE :
sval - > w = optindex ; /* Simple lists */
break ;
2013-01-03 21:23:20 +00:00
case OPT_PADDING :
sval - > w = * ( ( SANE_Word * ) value ) ;
break ;
2014-09-13 22:26:04 +00:00
/* case OPT_TRIALOPT: */
2012-07-01 01:28:14 +00:00
case OPT_PREVIEW : /* needed? */
sval - > w = * ( ( SANE_Word * ) value ) ;
break ;
default :
return SANE_STATUS_INVAL ;
}
if ( reload & & info ! = NULL )
* info | = SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS ;
DBG ( 17 , " %s: end \n " , __func__ ) ;
return SANE_STATUS_GOOD ;
}
SANE_Status
sane_control_option ( SANE_Handle handle , SANE_Int option , SANE_Action action ,
void * value , SANE_Int * info )
{
2012-12-31 20:13:32 +00:00
KodakAio_Scanner * s = ( KodakAio_Scanner * ) handle ;
2012-07-01 01:28:14 +00:00
if ( option < 0 | | option > = NUM_OPTIONS )
2013-01-03 21:23:20 +00:00
{
2013-11-05 14:31:11 +00:00
DBG ( 1 , " %s: option num = %d out of range (0..%d) \n " , __func__ , option , NUM_OPTIONS - 1 ) ;
2012-07-01 01:28:14 +00:00
return SANE_STATUS_INVAL ;
2013-01-03 21:23:20 +00:00
}
2012-07-01 01:28:14 +00:00
2014-12-31 10:26:07 +00:00
DBG ( 5 , " %s: action = %x, option = %d %s \n " , __func__ , action , option , s - > opt [ option ] . name ) ;
2013-11-05 14:31:11 +00:00
2012-07-01 01:28:14 +00:00
if ( info ! = NULL )
* info = 0 ;
switch ( action ) {
case SANE_ACTION_GET_VALUE :
return getvalue ( handle , option , value ) ;
case SANE_ACTION_SET_VALUE :
return setvalue ( handle , option , value , info ) ;
default :
return SANE_STATUS_INVAL ;
}
return SANE_STATUS_INVAL ;
}
SANE_Status
sane_get_parameters ( SANE_Handle handle , SANE_Parameters * params )
{
KodakAio_Scanner * s = ( KodakAio_Scanner * ) handle ;
DBG ( 2 , " %s: called \n " , __func__ ) ;
if ( params = = NULL )
DBG ( 1 , " %s: params is NULL \n " , __func__ ) ;
/*
* If sane_start was already called , then just retrieve the parameters
* from the scanner data structure
*/
if ( ! s - > eof & & s - > ptr ! = NULL ) {
DBG ( 5 , " scan in progress, returning saved params structure \n " ) ;
} else {
/* otherwise initialize the params structure and gather the data */
k_init_parametersta ( s ) ;
}
if ( params ! = NULL )
* params = s - > params ;
2012-12-23 21:23:43 +00:00
print_params ( s - > params , 20 ) ;
2012-07-01 01:28:14 +00:00
return SANE_STATUS_GOOD ;
}
/*
* 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 )
{
KodakAio_Scanner * s = ( KodakAio_Scanner * ) handle ;
SANE_Status status ;
DBG ( 2 , " %s: called \n " , __func__ ) ;
if ( ! s - > scanning ) {
2012-12-31 20:13:32 +00:00
/* calc scanning parameters */
status = k_init_parametersta ( s ) ;
if ( status ! = SANE_STATUS_GOOD )
return status ;
2012-07-01 01:28:14 +00:00
/* set scanning parameters; also query the current image
* parameters from the sanner and save
* them to s - > params
Only set scanning params the first time , or after a cancel
try change 22 / 2 / 12 take lock scanner out of k_set_scanning_parameters */
2014-12-31 10:26:07 +00:00
/* moved open_scanner here 27/12/14 from sane_open */
status = open_scanner ( s ) ;
if ( status ! = SANE_STATUS_GOOD ) {
free ( s ) ;
return status ;
}
/* end of open scanner section */
2012-12-31 20:13:32 +00:00
status = k_lock_scanner ( s ) ;
if ( status ! = SANE_STATUS_GOOD ) {
DBG ( 1 , " could not lock scanner \n " ) ;
return status ;
}
2012-07-01 01:28:14 +00:00
}
status = k_set_scanning_parameters ( s ) ;
if ( status ! = SANE_STATUS_GOOD )
return status ;
2012-12-23 21:23:43 +00:00
print_params ( s - > params , 5 ) ;
2012-07-01 01:28:14 +00:00
/* if we scan from ADF, check if it is loaded */
if ( strcmp ( source_list [ s - > val [ OPT_SOURCE ] . w ] , ADF_STR ) = = 0 ) {
status = k_check_adf ( s ) ;
if ( status ! = SANE_STATUS_GOOD ) {
2012-12-23 21:23:43 +00:00
/* returning SANE_STATUS_NO_DOCS seems not to cause simple-scan to end the adf scan, so we cancel */
2012-07-01 01:28:14 +00:00
status = SANE_STATUS_CANCELLED ;
2012-12-23 21:23:43 +00:00
DBG ( 10 , " %s: returning %s \n " , __func__ , sane_strstatus ( status ) ) ;
2012-07-01 01:28:14 +00:00
return status ;
}
}
/* prepare buffer here so that a memory allocation failure
* will leave the scanner in a sane state .
*/
s - > buf = realloc ( s - > buf , s - > block_len ) ;
if ( s - > buf = = NULL )
return SANE_STATUS_NO_MEM ;
2012-12-31 20:13:32 +00:00
s - > eof = SANE_FALSE ; /* page not finished */
s - > ack = SANE_FALSE ; /* page from scanner not finished */
2012-07-01 01:28:14 +00:00
s - > ptr = s - > end = s - > buf ;
s - > canceling = SANE_FALSE ;
2012-12-31 20:13:32 +00:00
if ( strlen ( RawScanPath ) > 0 & & s - > params . lines > 0 )
2012-07-01 01:28:14 +00:00
RawScan = fopen ( RawScanPath , " wb " ) ; /* open the debug file if it has a name */
if ( RawScan ) fprintf ( RawScan , " P5 \n %d %d \n %d \n " , s - > scan_bytes_per_line , s - > params . lines , 255 ) ;
/* start scanning */
DBG ( 2 , " %s: scanning... \n " , __func__ ) ;
status = k_start_scan ( s ) ;
if ( status ! = SANE_STATUS_GOOD ) {
DBG ( 1 , " %s: start failed: %s \n " , __func__ ,
sane_strstatus ( status ) ) ;
return status ;
}
return status ;
}
/* this moves data from our buffers to SANE */
SANE_Status
sane_read ( SANE_Handle handle , SANE_Byte * data , SANE_Int max_length ,
SANE_Int * length )
{
SANE_Status status ;
KodakAio_Scanner * s = ( KodakAio_Scanner * ) handle ;
if ( s - > buf = = NULL | | s - > canceling )
return SANE_STATUS_CANCELLED ;
* length = 0 ;
DBG ( 18 , " sane-read, bytes unread %d \n " , s - > bytes_unread ) ;
2012-12-23 21:23:43 +00:00
status = k_read ( s ) ;
2012-07-01 01:28:14 +00:00
if ( status = = SANE_STATUS_CANCELLED ) {
k_scan_finish ( s ) ;
return status ;
}
2012-12-23 21:23:43 +00:00
k_copy_image_data ( s , data , max_length , length ) ;
2012-07-01 01:28:14 +00:00
DBG ( 18 , " %d lines read, status: %s \n " ,
* length / s - > params . bytes_per_line , sane_strstatus ( status ) ) ;
/* continue reading if appropriate */
if ( status = = SANE_STATUS_GOOD )
return status ;
/* not sure if we want to finish (unlock scanner) here or in sane_close */
/* k_scan_finish(s); */
return status ;
}
void
sane_cancel ( SANE_Handle handle )
{
2014-12-31 10:26:07 +00:00
SANE_Status status ;
2012-07-01 01:28:14 +00:00
KodakAio_Scanner * s = ( KodakAio_Scanner * ) handle ;
DBG ( 2 , " %s: called \n " , __func__ ) ;
2014-12-31 10:26:07 +00:00
status = cmd_cancel_scan ( s ) ;
if ( status ! = SANE_STATUS_GOOD )
DBG ( 1 , " %s: cmd_cancel_scan failed: %s \n " , __func__ ,
sane_strstatus ( status ) ) ;
/* moved from close scanner section 27/12/14 */
if ( s - > fd ! = - 1 )
close_scanner ( s ) ;
/* end of section */
2012-07-01 01:28:14 +00:00
}
/*
* SANE_Status sane_set_io_mode ( )
*
* not supported - for asynchronous I / O
*/
SANE_Status
sane_set_io_mode ( SANE_Handle __sane_unused__ handle ,
SANE_Bool __sane_unused__ non_blocking )
{
return SANE_STATUS_UNSUPPORTED ;
}
/*
* SANE_Status sane_get_select_fd ( )
*
* not supported - for asynchronous I / O
*/
SANE_Status
sane_get_select_fd ( SANE_Handle __sane_unused__ handle ,
SANE_Int __sane_unused__ * fd )
{
return SANE_STATUS_UNSUPPORTED ;
}