2009-01-05 Jeremy Johnson <jeremy a t acjlaw dot net>

Added code to read_data() to pad image data to
	requested length and to zero out any garbage using
	information from sense data command. Added new
	MAINTENANCE_DATA struct and options to display
	scanner's maintenance/callibration statistics.
	*backend/hs2p.h
	- added enum CONNECTION_TYPES
	- added HS2P_DATA struct
	- added SENSE_DATA struct to struct HS2P_Device
	- added SANE_String_Const orientation_list[]
	- added macros isset_ILI() and isset_EOM()
	*backend/hs2p-scsi.h
	- replaced request_sense struct with SENSE_DATA struct
	- added #define DATA_TYPE_EOL (va_list sentinel)
	- added MAINTENANCE_DATA struct
	*backend/hs2p-saneopts.h
	- added OPT_ORIENTATION
	- added MAINTENANCE_DATA options
	*backend/hs2p.c
	- added MAINTENANCE_DATA options
	- added unused connType to attach()
	- added update_hs2p_data() to fill in options
	- added hs2p_open() and hs2p_close()
	- added get_hs2p_data() to read scanner data
	- added print_maintenance_data()
	- modified sane_control_options() to
	  accomodate new maintenance options and to
	  handle Portrait/Landscape option
	  replaced adf_status macro with s->data.adf_status
	- modified sane_read() to correctly zero out the
	  missing bytes on an incomplete read and to pad
	  to the requested length
	*backend/hs2p-scsi.c
	- replaced request_sense() with get_sense_data()
	- added print_sense_data()
	- added SENSE_DATA *sdp to sense_handler()
	- modified read_data() to handler other data type codes/qualifiers
	- read_adf_status() now is replaced with call to
	  read_data(fd,*buf,*bufsize,dtc,dtq)
merge-requests/1/head
Jeremy Johnson 2009-01-06 01:21:19 +00:00
rodzic 27d1561afb
commit e11de37747
6 zmienionych plików z 937 dodań i 77 usunięć

Wyświetl plik

@ -1,3 +1,44 @@
2009-01-05 Jeremy Johnson <jeremy a t acjlaw dot net>
Added code to read_data() to pad image data to
requested length and to zero out any garbage using
information from sense data command. Added new
MAINTENANCE_DATA struct and options to display
scanner's maintenance/callibration statistics.
*backend/hs2p.h
- added enum CONNECTION_TYPES
- added HS2P_DATA struct
- added SENSE_DATA struct to struct HS2P_Device
- added SANE_String_Const orientation_list[]
- added macros isset_ILI() and isset_EOM()
*backend/hs2p-scsi.h
- replaced request_sense struct with SENSE_DATA struct
- added #define DATA_TYPE_EOL (va_list sentinel)
- added MAINTENANCE_DATA struct
*backend/hs2p-saneopts.h
- added OPT_ORIENTATION
- added MAINTENANCE_DATA options
*backend/hs2p.c
- added MAINTENANCE_DATA options
- added unused connType to attach()
- added update_hs2p_data() to fill in options
- added hs2p_open() and hs2p_close()
- added get_hs2p_data() to read scanner data
- added print_maintenance_data()
- modified sane_control_options() to
accomodate new maintenance options and to
handle Portrait/Landscape option
replaced adf_status macro with s->data.adf_status
- modified sane_read() to correctly zero out the
missing bytes on an incomplete read and to pad
to the requested length
*backend/hs2p-scsi.c
- replaced request_sense() with get_sense_data()
- added print_sense_data()
- added SENSE_DATA *sdp to sense_handler()
- modified read_data() to handler other data type codes/qualifiers
- read_adf_status() now is replaced with call to
read_data(fd,*buf,*bufsize,dtc,dtq)
2009-01-04 Nicolas Martin <nicols-guest at users.alioth.debian.org>
* doc/sane-pixma.man, doc/descriptions/pixma.desc:
Updated doc for pixma backend (ImageClass)

Wyświetl plik

@ -169,6 +169,10 @@
#define SANE_TITLE_ICON_LENGTH "Icon Length"
#define SANE_DESC_ICON_LENGTH "Length of icon (thumbnail) image in pixels"
#define SANE_NAME_ORIENTATION "orientation"
#define SANE_TITLE_ORIENTATION "Paper Orientation"
#define SANE_DESC_ORIENTATION "[Portrait]/Landscape" \
#define SANE_NAME_PAPER_SIZE "paper-size"
#define SANE_TITLE_PAPER_SIZE "Paper Size"
#define SANE_DESC_PAPER_SIZE "Specify the scan window geometry by specifying the paper size " \
@ -283,6 +287,7 @@ typedef enum
/*OPT_AUTOBORDER, automatic border detection */
/*OPT_ROTATION, hardware rotation */
/*OPT_DESKEW, hardware deskew */
OPT_PAGE_ORIENTATION, /* portrait, landscape */
OPT_PAPER_SIZE, /* paper size */
OPT_TL_X, /* top-left x */
OPT_TL_Y, /* top-left y */
@ -332,5 +337,29 @@ typedef enum
OPT_SECTION
*/
OPT_DATA_GROUP,
OPT_UPDATE,
OPT_NREGX_ADF,
OPT_NREGY_ADF,
OPT_NREGX_BOOK,
OPT_NREGY_BOOK,
OPT_NSCANS_ADF,
OPT_NSCANS_BOOK,
OPT_LAMP_TIME,
OPT_EO_ODD,
OPT_EO_EVEN,
OPT_BLACK_LEVEL_ODD,
OPT_BLACK_LEVEL_EVEN,
OPT_WHITE_LEVEL_ODD,
OPT_WHITE_LEVEL_EVEN,
OPT_DENSITY,
OPT_FIRST_ADJ_WHITE_ODD,
OPT_FIRST_ADJ_WHITE_EVEN,
OPT_NREGX_REVERSE,
OPT_NREGY_REVERSE,
OPT_NSCANS_REVERSE_ADF,
OPT_REVERSE_TIME,
OPT_NCHARS,
NUM_OPTIONS /* must come last: */
} HS2P_Option;

Wyświetl plik

@ -322,23 +322,67 @@ test_unit_ready (int fd)
Byte4: | Allocation Length |
Byte5: | 7-6 Vendor Unique | 5-2 Reserved | 1 Flag | 0 Link |
*/
#if 0
static SANE_Status
request_sense (int fd)
get_sense_data (int fd, SENSE_DATA * sense_data)
{
static SANE_Byte cmd[6];
SANE_Status status;
DBG (DBG_proc, ">> request sense\n");
DBG (DBG_sane_proc, ">> get_sense_data\n");
static SANE_Byte cmd[6];
size_t len;
len = sizeof (*sense_data);
memset (sense_data, 0, len);
memset (cmd, 0, sizeof (cmd));
cmd[0] = HS2P_SCSI_REQUEST_SENSE;
memset (cmd, 0, sizeof (cmd));
status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0);
cmd[4] = len;
DBG (DBG_proc, "<< request_sense\n");
status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), sense_data, &len);
DBG (DBG_proc, "<< get_sense_data\n");
return (status);
}
#endif
static SANE_Status
print_sense_data (int dbg_level, SENSE_DATA * data)
{
SANE_Status status = SANE_STATUS_GOOD;
SANE_Byte *bp, *end;
SANE_Int i;
DBG (DBG_sane_proc, ">> print_sense_data\n");
bp = (SANE_Byte *) data;
end = bp + (SANE_Byte) sizeof (SENSE_DATA);
for (i = 0; bp < end; bp++, i++)
{
DBG (dbg_level, "Byte #%2d is %3d, 0x%02x\n", i, *bp, *bp);
}
DBG (dbg_level, "Valid=%1d, ErrorCode=%#x\n",
(data->error_code & 0x80) >> 7, data->error_code & 0x7F);
DBG (dbg_level, "Segment number = %d\n", data->segment_number);
DBG (dbg_level,
"F-mark=%1d, EOM=%1d, ILI=%1d, Reserved=%1d, SenseKey=%#x\n",
(data->sense_key & 0x80) >> 7, (data->sense_key & 0x40) >> 6,
(data->sense_key & 0x20) >> 5, (data->sense_key & 0x10) >> 4,
(data->sense_key & 0x0F));
DBG (dbg_level, "Information Byte = %lu\n", _4btol (data->information));
DBG (dbg_level, "Additional Sense Length = %d\n", data->sense_length);
DBG (dbg_level, "Command Specific Infomation = %lu\n",
_4btol (data->command_specific_information));
DBG (dbg_level, "Additional Sense Code = %#x\n", data->sense_code);
DBG (dbg_level, "Additional Sense Code Qualifier = %#x\n",
data->sense_code_qualifier);
DBG (DBG_proc, "<< print_sense_data\n");
return (status);
}
static struct sense_key *
lookup_sensekey_errmsg (int code)
{
@ -382,42 +426,50 @@ lookup_ascq_errmsg (unsigned int code)
Byte 13: Additional Sense Code Qualifier
*/
static SANE_Status
sense_handler (int scsi_fd, u_char * result, void *arg)
sense_handler (int __sane_unused__ scsi_fd, u_char * sense_buffer, void *sd)
{
u_char sense, asc, ascq, EOM, ILI, ErrorCode, ValidData;
u_long InvalidBytes;
u_long MissingBytes;
char *sense_str = "";
struct sense_key *skey;
struct ASCQ *ascq_key;
SENSE_DATA *sdp = (SENSE_DATA *) sd;
SANE_Int i;
SANE_Status status = SANE_STATUS_INVAL;
SANE_Char print_sense[(16 * 3) + 1];
DBG (DBG_proc, ">> sense_handler\n");
(void) arg;
if (DBG_LEVEL >= DBG_info)
print_sense_data (DBG_LEVEL, (SENSE_DATA *) sense_buffer);
scsi_fd = scsi_fd; /* get rid of compiler warning */
ErrorCode = result[0] & 0x7F;
ValidData = (result[0] & 0x80) != 0;
sense = result[2] & 0x0f; /* Sense Key */
asc = result[12]; /* Additional Sense Code */
ascq = result[13]; /* Additional Sense Code Qualifier */
EOM = (result[2] & 0x40) != 0; /* End Of Media */
ILI = (result[2] & 0x20) != 0; /* Invalid Length Indicator */
InvalidBytes = ValidData ? _4btol (&result[3]) : 0;
/* store sense_buffer */
DBG (DBG_info, ">> copying %d bytes from sense_buffer[] to sense_data\n",
sizeof (SENSE_DATA));
memcpy (sdp, sense_buffer, sizeof (SENSE_DATA));
if (DBG_LEVEL >= DBG_info)
print_sense_data (DBG_LEVEL, sdp);
DBG (DBG_sense, "sense_handler: result=%#x, sense=%#x, asc=%#x, ascq=%#x\n",
result[0], sense, asc, ascq);
ErrorCode = sense_buffer[0] & 0x7F;
ValidData = (sense_buffer[0] & 0x80) != 0;
sense = sense_buffer[2] & 0x0f; /* Sense Key */
asc = sense_buffer[12]; /* Additional Sense Code */
ascq = sense_buffer[13]; /* Additional Sense Code Qualifier */
EOM = (sense_buffer[2] & 0x40) != 0; /* End Of Media */
ILI = (sense_buffer[2] & 0x20) != 0; /* Invalid Length Indicator */
MissingBytes = ValidData ? _4btol (&sense_buffer[3]) : 0;
DBG (DBG_sense,
"sense_handler: sense_buffer=%#x, sense=%#x, asc=%#x, ascq=%#x\n",
sense_buffer[0], sense, asc, ascq);
DBG (DBG_sense,
"sense_handler: ErrorCode %02x ValidData: %d "
"EOM: %d ILI: %d InvalidBytes: %lu\n", ErrorCode, ValidData, EOM, ILI,
InvalidBytes);
"EOM: %d ILI: %d MissingBytes: %lu\n", ErrorCode, ValidData, EOM,
ILI, MissingBytes);
memset (print_sense, '\0', sizeof (print_sense));
for (i = 0; i < 16; i++)
sprintf (print_sense + strlen (print_sense), "%02x ", result[i]);
sprintf (print_sense + strlen (print_sense), "%02x ", sense_buffer[i]);
DBG (DBG_sense, "sense_handler: sense=%s\n", print_sense);
if (ErrorCode != 0x70 && ErrorCode != 0x71)
@ -1102,16 +1154,28 @@ print_window_data (SWD * buf)
}
static SANE_Status
read_data (int fd, void *buf, size_t * buf_size)
read_data (int fd, void *buf, size_t * buf_size, SANE_Byte dtc, u_long dtq)
{
static struct scsi_rs_scanner_cmd cmd;
SANE_Status status;
DBG (DBG_proc, ">> read_data %lu\n", (unsigned long) *buf_size);
DBG (DBG_proc, ">> read_data buf_size=%lu dtc=0x%2.2x dtq=%lu\n",
(unsigned long) *buf_size, (int) dtc, dtq);
if (fd < 0)
{
DBG (DBG_error, "read_data: scanner is closed!\n");
return SANE_STATUS_INVAL;
}
memset (&cmd, 0, sizeof (cmd)); /* CLEAR */
cmd.opcode = HS2P_SCSI_READ_DATA;
cmd.dtc = DATA_TYPE_IMAGE;
cmd.dtc = dtc;
_lto2b (dtq, cmd.dtq);
_lto3b (*buf_size, cmd.len);
DBG (DBG_info, "read_data ready to send scsi cmd\n");
DBG (DBG_info, "opcode=0x%2.2x, dtc=0x%2.2x, dtq=%lu, transfer len =%d\n",
cmd.opcode, cmd.dtc, _2btol (cmd.dtq), _3btol (cmd.len));
status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), buf, buf_size);
if (status != SANE_STATUS_GOOD)
@ -1407,7 +1471,9 @@ read_size_data (int fd)
SANE_Status status = SANE_STATUS_GOOD;
return (status);
}
#endif
#if 0
static SANE_Status
read_maintenance_data (int fd)
{
@ -1421,6 +1487,9 @@ read_maintenance_data (int fd)
* Bit2: reserved
* Bits7-3: reserved
*/
#if 0
static SANE_Status
read_adf_status (int fd, SANE_Byte * adf_status_byte)
{
@ -1440,10 +1509,10 @@ read_adf_status (int fd, SANE_Byte * adf_status_byte)
{
DBG (DBG_error, "read_adf_status ERROR: %s\n", sane_strstatus (status));
}
DBG (DBG_proc, "<< read_adf_status\n");
return (status);
}
#endif
/*
* read_ipu_photoletter_parameters

Wyświetl plik

@ -217,7 +217,7 @@ static struct ASCQ ascq_errmsg[74] = {
{0x8c00, "Size detection failed"}
};
struct request_sense
typedef struct sense_data
{ /* HS2P_REQUEST_SENSE_DATA */
/* bit7:valid is 1 if information byte is valid,
bits6:0 error_code */
@ -241,7 +241,7 @@ struct request_sense
SANE_Byte command_specific_information[4];
SANE_Byte sense_code;
SANE_Byte sense_code_qualifier;
};
} SENSE_DATA;
/* page codes used with HS2P_SCSI_INQUIRY */
#define HS2P_INQUIRY_STANDARD_PAGE_CODE 0x00
@ -1065,8 +1065,10 @@ typedef struct get_window_data
/* 92H Reserved (Scanner Extension I/O Access) */
/* 93H Reserved (Vendor Unique) */
/* 94H-FFH Reserved (Vendor Unique) */
#define DATA_TYPE_EOL -1 /* va_end */
/* DATA TYPE QUALIFIER CODES when DTC=93H */
#define DTQ 0x00 /* ignored */
#define DTQ_AUTO_PHOTOLETTER 0x00 /* default */
#define DTQ_DYNAMIC_THRESHOLDING 0x01 /* default */
#define DTQ_LIGHT_CHARS_ENHANCEMENT 0x02
@ -1120,32 +1122,34 @@ struct scsi_rs_scanner_cmd
* PAGE LENGTH: 5bytes: 1st byte is MSB, Last byte is LSB
*/
struct
typedef struct maintenance_data
{
SANE_Byte nregx_adf; /* number of registers of main-scanning in ADF mode */
SANE_Byte nregy_adf; /* number of registers of sub-scanning in ADF mode */
SANE_Byte nregx_book; /* number of registers of main-scanning in Book mode */
SANE_Byte nregy_book; /* number of registers of sub-scanning in Book mode */
SANE_Byte nscans_adf[5]; /* Number of scanned pages in ADF mode */
SANE_Byte nscans_book[5]; /* Number of scanned pages in Book mode */
SANE_Byte nscans_adf[4]; /* Number of scanned pages in ADF mode */
SANE_Byte nscans_book[4]; /* Number of scanned pages in Book mode */
SANE_Byte lamp_time[4]; /* Lamp Time */
SANE_Byte eo_odd; /* Adjustment data of E/O balance in black level (ODD) */
SANE_Byte eo_even; /* Adjustment data of E/O balance in black level (EVEN) */
SANE_Byte black_level_odd; /* The adjustment data in black level (ODD) */
SANE_Byte black_level_even; /* The adjustment data in black level (EVEN) */
SANE_Byte white_odd[2]; /* The adjustment data in white level (ODD) */
SANE_Byte white_even[2]; /* The adjustment data in white level (EVEN) */
SANE_Byte white_level_odd[2]; /* The adjustment data in white level (ODD) */
SANE_Byte white_level_even[2]; /* The adjustment data in white level (EVEN) */
SANE_Byte first_adj_white_odd[2]; /* First adjustment data in white level (ODD) */
SANE_Byte first_adj_white_even[2]; /* First adjustment data in white level (EVEN) */
SANE_Byte density_adj; /* Density adjustment */
SANE_Byte nregx_reverse; /* The number of registers of main-scanning of the reverse-side ADF */
SANE_Byte nregy_reverse; /* The number of registers of sub-scanning of the reverse-side ADF */
SANE_Byte nscans_reverse_adf[5]; /* Number of scanned pages of the reverse side ADF */
SANE_Byte duration[4]; /* The period of lamp turn on of the reverse side */
SANE_Byte nscans_reverse_adf[4]; /* Number of scanned pages of the reverse side ADF */
SANE_Byte reverse_time[4]; /* The period of lamp turn on of the reverse side */
SANE_Byte nchars[4]; /* The number of endorser characters */
SANE_Byte reserved0;
SANE_Byte reserved1;
SANE_Byte reserved2;
SANE_Byte zero[2]; /* All set as 0 */
} maintenance_data;
} MAINTENANCE_DATA;
/* ADF status 1byte:
* 7-3:Reserved;
* 2:Reserved;

Wyświetl plik

@ -341,13 +341,23 @@ init_options (HS2P_Scanner * s)
s->opt[OPT_PADDING].constraint_type = SANE_CONSTRAINT_NONE;
s->val[OPT_PADDING].w = SANE_TRUE;
/*if (!s->hw->info.hasADF)
s->opt[OPT_PADDING].cap |= SANE_CAP_INACTIVE;
FIXME: compare to user setting, not the existence of FB?
if (!strcmp (scan_source_list, "FB"))
s->opt[OPT_PADDING].cap |= SANE_CAP_INACTIVE;*/
s->opt[OPT_PADDING].cap |= SANE_CAP_INACTIVE;
FIXME: compare to user setting, not the existence of FB?
if (!strcmp (scan_source_list, "FB"))
s->opt[OPT_PADDING].cap |= SANE_CAP_INACTIVE; */
/* Permanently disable OPT_PADDING */
s->opt[OPT_PADDING].cap |= SANE_CAP_INACTIVE;
/* Paper Orientation */
s->opt[OPT_PAGE_ORIENTATION].name = SANE_NAME_ORIENTATION;
s->opt[OPT_PAGE_ORIENTATION].title = SANE_TITLE_ORIENTATION;
s->opt[OPT_PAGE_ORIENTATION].desc = SANE_DESC_ORIENTATION;
s->opt[OPT_PAGE_ORIENTATION].type = SANE_TYPE_STRING;
s->opt[OPT_PAGE_ORIENTATION].size = max_string_size (orientation_list);
s->opt[OPT_PAGE_ORIENTATION].constraint_type = SANE_CONSTRAINT_STRING_LIST;
s->opt[OPT_PAGE_ORIENTATION].constraint.string_list = &orientation_list[0];
s->val[OPT_PAGE_ORIENTATION].s = strdup (orientation_list[0]);
/* Paper Size */
s->opt[OPT_PAPER_SIZE].name = SANE_NAME_PAPER_SIZE;
s->opt[OPT_PAPER_SIZE].title = SANE_TITLE_PAPER_SIZE;
@ -749,12 +759,207 @@ init_options (HS2P_Scanner * s)
s->opt[OPT_OPTICAL_ADJUSTMENT].desc = SANE_DESC_OPTICAL_ADJUSTMENT;
s->opt[OPT_OPTICAL_ADJUSTMENT].type = SANE_TYPE_BUTTON;
/* MAINTENANCE DATA */
s->opt[OPT_DATA_GROUP].name = "";
s->opt[OPT_DATA_GROUP].title = "Maintenance Data";
s->opt[OPT_DATA_GROUP].desc = "";
s->opt[OPT_DATA_GROUP].type = SANE_TYPE_GROUP;
s->opt[OPT_DATA_GROUP].cap = SANE_CAP_ADVANCED;
s->opt[OPT_DATA_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_UPDATE].name = "Update";
s->opt[OPT_UPDATE].title = "Update";
s->opt[OPT_UPDATE].desc = "Update scanner data";
s->opt[OPT_UPDATE].type = SANE_TYPE_BUTTON;
s->opt[OPT_NREGX_ADF].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_NREGX_ADF].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_NREGX_ADF].name = "# registers in main-scanning in ADF mode";
s->opt[OPT_NREGX_ADF].title = "# registers in main-scanning in ADF mode";
s->opt[OPT_NREGX_ADF].desc = "# registers in main-scanning in ADF mode";
s->opt[OPT_NREGX_ADF].type = SANE_TYPE_INT;
s->opt[OPT_NREGX_ADF].unit = SANE_UNIT_NONE;
s->opt[OPT_NREGX_ADF].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_NREGX_ADF].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_NREGY_ADF].name = "# registers in sub-scanning in ADF mode";
s->opt[OPT_NREGY_ADF].title = "# registers in sub-scanning in ADF mode";
s->opt[OPT_NREGY_ADF].desc = "# registers in sub-scanning in ADF mode";
s->opt[OPT_NREGY_ADF].type = SANE_TYPE_INT;
s->opt[OPT_NREGY_ADF].unit = SANE_UNIT_NONE;
s->opt[OPT_NREGY_ADF].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_NREGY_ADF].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_NREGX_BOOK].name = "# registers in main-scanning in book mode";
s->opt[OPT_NREGX_BOOK].title = "# registers in main-scanning in book mode";
s->opt[OPT_NREGX_BOOK].desc = "# registers in main-scanning in book mode";
s->opt[OPT_NREGX_BOOK].type = SANE_TYPE_INT;
s->opt[OPT_NREGX_BOOK].unit = SANE_UNIT_NONE;
s->opt[OPT_NREGX_BOOK].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_NREGX_BOOK].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_NREGY_BOOK].name = "# registers in sub-scanning in book mode";
s->opt[OPT_NREGY_BOOK].title = "# registers in sub-scanning in book mode";
s->opt[OPT_NREGY_BOOK].desc = "# registers in sub-scanning in book mode";
s->opt[OPT_NREGY_BOOK].type = SANE_TYPE_INT;
s->opt[OPT_NREGY_BOOK].unit = SANE_UNIT_NONE;
s->opt[OPT_NREGY_BOOK].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_NREGY_BOOK].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_NSCANS_ADF].name = "# ADF Scans";
s->opt[OPT_NSCANS_ADF].title = "# ADF Scans";
s->opt[OPT_NSCANS_ADF].desc = "# ADF Scans";
s->opt[OPT_NSCANS_ADF].type = SANE_TYPE_INT;
s->opt[OPT_NSCANS_ADF].unit = SANE_UNIT_NONE;
s->opt[OPT_NSCANS_ADF].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_NSCANS_ADF].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_NSCANS_BOOK].name = "# BOOK Scans";
s->opt[OPT_NSCANS_BOOK].title = "# BOOK Scans";
s->opt[OPT_NSCANS_BOOK].desc = "# BOOK Scans";
s->opt[OPT_NSCANS_BOOK].type = SANE_TYPE_INT;
s->opt[OPT_NSCANS_BOOK].unit = SANE_UNIT_NONE;
s->opt[OPT_NSCANS_BOOK].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_NSCANS_BOOK].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_LAMP_TIME].name = "LAMP TIME";
s->opt[OPT_LAMP_TIME].title = "LAMP TIME";
s->opt[OPT_LAMP_TIME].desc = "LAMP TIME";
s->opt[OPT_LAMP_TIME].type = SANE_TYPE_INT;
s->opt[OPT_LAMP_TIME].unit = SANE_UNIT_NONE;
s->opt[OPT_LAMP_TIME].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_LAMP_TIME].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_EO_ODD].name = "E/O Balance ODD";
s->opt[OPT_EO_ODD].title = "E/O Balance ODD";
s->opt[OPT_EO_ODD].desc = "Adj. of E/O Balance in black level ODD";
s->opt[OPT_EO_ODD].type = SANE_TYPE_INT;
s->opt[OPT_EO_ODD].unit = SANE_UNIT_NONE;
s->opt[OPT_EO_ODD].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_EO_ODD].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_EO_EVEN].name = "E/O Balance EVEN";
s->opt[OPT_EO_EVEN].title = "E/O Balance EVEN";
s->opt[OPT_EO_EVEN].desc = "Adj. of E/O Balance in black level EVEN";
s->opt[OPT_EO_EVEN].type = SANE_TYPE_INT;
s->opt[OPT_EO_EVEN].unit = SANE_UNIT_NONE;
s->opt[OPT_EO_EVEN].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_EO_EVEN].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_BLACK_LEVEL_ODD].name = "Black Level ODD";
s->opt[OPT_BLACK_LEVEL_ODD].title = "Black Level ODD";
s->opt[OPT_BLACK_LEVEL_ODD].desc = "Adj. data in black level (ODD)";
s->opt[OPT_BLACK_LEVEL_ODD].type = SANE_TYPE_INT;
s->opt[OPT_BLACK_LEVEL_ODD].unit = SANE_UNIT_NONE;
s->opt[OPT_BLACK_LEVEL_ODD].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_BLACK_LEVEL_ODD].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_BLACK_LEVEL_EVEN].name = "Black Level EVEN";
s->opt[OPT_BLACK_LEVEL_EVEN].title = "Black Level EVEN";
s->opt[OPT_BLACK_LEVEL_EVEN].desc = "Adj. data in black level (EVEN)";
s->opt[OPT_BLACK_LEVEL_EVEN].type = SANE_TYPE_INT;
s->opt[OPT_BLACK_LEVEL_EVEN].unit = SANE_UNIT_NONE;
s->opt[OPT_BLACK_LEVEL_EVEN].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_BLACK_LEVEL_EVEN].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_WHITE_LEVEL_ODD].name = "White Level ODD";
s->opt[OPT_WHITE_LEVEL_ODD].title = "White Level ODD";
s->opt[OPT_WHITE_LEVEL_ODD].desc = "Adj. data in White level (ODD)";
s->opt[OPT_WHITE_LEVEL_ODD].type = SANE_TYPE_INT;
s->opt[OPT_WHITE_LEVEL_ODD].unit = SANE_UNIT_NONE;
s->opt[OPT_WHITE_LEVEL_ODD].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_WHITE_LEVEL_ODD].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_WHITE_LEVEL_EVEN].name = "White Level EVEN";
s->opt[OPT_WHITE_LEVEL_EVEN].title = "White Level EVEN";
s->opt[OPT_WHITE_LEVEL_EVEN].desc = "Adj. data in White level (EVEN)";
s->opt[OPT_WHITE_LEVEL_EVEN].type = SANE_TYPE_INT;
s->opt[OPT_WHITE_LEVEL_EVEN].unit = SANE_UNIT_NONE;
s->opt[OPT_WHITE_LEVEL_EVEN].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_WHITE_LEVEL_EVEN].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_WHITE_LEVEL_EVEN].name = "White Level EVEN";
s->opt[OPT_WHITE_LEVEL_EVEN].title = "White Level EVEN";
s->opt[OPT_WHITE_LEVEL_EVEN].desc = "Adj. data in White level (EVEN)";
s->opt[OPT_WHITE_LEVEL_EVEN].type = SANE_TYPE_INT;
s->opt[OPT_WHITE_LEVEL_EVEN].unit = SANE_UNIT_NONE;
s->opt[OPT_WHITE_LEVEL_EVEN].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_WHITE_LEVEL_EVEN].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_DENSITY].name = "Density Adjustment";
s->opt[OPT_DENSITY].title = "Density Adjustment";
s->opt[OPT_DENSITY].desc = "Density adjustment of std. white board";
s->opt[OPT_DENSITY].type = SANE_TYPE_INT;
s->opt[OPT_DENSITY].unit = SANE_UNIT_NONE;
s->opt[OPT_DENSITY].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_DENSITY].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_FIRST_ADJ_WHITE_ODD].name = "1st adj. in white level (ODD)";
s->opt[OPT_FIRST_ADJ_WHITE_ODD].title = "1st adj. in white level (ODD)";
s->opt[OPT_FIRST_ADJ_WHITE_ODD].desc = "1st adj. in white level (ODD)";
s->opt[OPT_FIRST_ADJ_WHITE_ODD].type = SANE_TYPE_INT;
s->opt[OPT_FIRST_ADJ_WHITE_ODD].unit = SANE_UNIT_NONE;
s->opt[OPT_FIRST_ADJ_WHITE_ODD].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_FIRST_ADJ_WHITE_ODD].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_FIRST_ADJ_WHITE_EVEN].name = "1st adj. in white level (EVEN)";
s->opt[OPT_FIRST_ADJ_WHITE_EVEN].title = "1st adj. in white level (EVEN)";
s->opt[OPT_FIRST_ADJ_WHITE_EVEN].desc = "1st adj. in white level (EVEN)";
s->opt[OPT_FIRST_ADJ_WHITE_EVEN].type = SANE_TYPE_INT;
s->opt[OPT_FIRST_ADJ_WHITE_EVEN].unit = SANE_UNIT_NONE;
s->opt[OPT_FIRST_ADJ_WHITE_EVEN].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_FIRST_ADJ_WHITE_EVEN].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_NREGX_REVERSE].name = "# registers of main-scanning of backside";
s->opt[OPT_NREGX_REVERSE].title =
"# registers of main-scanning of backside";
s->opt[OPT_NREGX_REVERSE].desc =
"# registers of main-scanning of ADF backside";
s->opt[OPT_NREGX_REVERSE].type = SANE_TYPE_INT;
s->opt[OPT_NREGX_REVERSE].unit = SANE_UNIT_NONE;
s->opt[OPT_NREGX_REVERSE].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_NREGX_REVERSE].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_NREGY_REVERSE].name = "# registers of sub-scanning of backside";
s->opt[OPT_NREGY_REVERSE].title = "# registers of sub-scanning of backside";
s->opt[OPT_NREGY_REVERSE].desc =
"# registers of sub-scanning of ADF backside";
s->opt[OPT_NREGY_REVERSE].type = SANE_TYPE_INT;
s->opt[OPT_NREGY_REVERSE].unit = SANE_UNIT_NONE;
s->opt[OPT_NREGY_REVERSE].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_NREGY_REVERSE].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_NSCANS_REVERSE_ADF].name = "# of scans of reverse side in ADF";
s->opt[OPT_NSCANS_REVERSE_ADF].title = "# of scans of reverse side in ADF";
s->opt[OPT_NSCANS_REVERSE_ADF].desc = "# of scans of reverse side in ADF";
s->opt[OPT_NSCANS_REVERSE_ADF].type = SANE_TYPE_INT;
s->opt[OPT_NSCANS_REVERSE_ADF].unit = SANE_UNIT_NONE;
s->opt[OPT_NSCANS_REVERSE_ADF].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_NSCANS_REVERSE_ADF].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_REVERSE_TIME].name = "LAMP TIME (reverse)";
s->opt[OPT_REVERSE_TIME].title = "LAMP TIME (reverse)";
s->opt[OPT_REVERSE_TIME].desc = "LAMP TIME (reverse)";
s->opt[OPT_REVERSE_TIME].type = SANE_TYPE_INT;
s->opt[OPT_REVERSE_TIME].unit = SANE_UNIT_NONE;
s->opt[OPT_REVERSE_TIME].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_REVERSE_TIME].constraint_type = SANE_CONSTRAINT_NONE;
s->opt[OPT_NCHARS].name = "# of endorser characters";
s->opt[OPT_NCHARS].title = "# of endorser characters";
s->opt[OPT_NCHARS].desc = "# of endorser characters";
s->opt[OPT_NCHARS].type = SANE_TYPE_INT;
s->opt[OPT_NCHARS].unit = SANE_UNIT_NONE;
s->opt[OPT_NCHARS].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_NCHARS].constraint_type = SANE_CONSTRAINT_NONE;
DBG (DBG_proc, "<< init_options\n");
return SANE_STATUS_GOOD;
}
static SANE_Status
attach (SANE_String_Const devname, HS2P_Device ** devp)
attach (SANE_String_Const devname, int __sane_unused__ connType,
HS2P_Device ** devp)
{
SANE_Status status;
HS2P_Device *dev;
@ -783,13 +988,16 @@ attach (SANE_String_Const devname, HS2P_Device ** devp)
}
}
DBG (DBG_sane_proc, ">>> attach: opening \"%s\"\n", devname);
status = sanei_scsi_open (devname, &fd, sense_handler, NULL);
/* sanei_scsi_open takes an option bufsize argument */
status = sanei_scsi_open (devname, &fd, &sense_handler, &(dev->sense_data));
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, ">>> attach: open failed: %s\n",
sane_strstatus (status));
return (status);
}
DBG (DBG_sane_proc, ">>> attach: opened %s fd=%d\n", devname, fd);
DBG (DBG_sane_proc, ">>> attach: sending INQUIRY (standard data)\n");
@ -1239,8 +1447,8 @@ attach (SANE_String_Const devname, HS2P_Device ** devp)
static SANE_Status
attach_one_scsi (const char *devname)
{
attach (devname, NULL);
return SANE_STATUS_GOOD;
return attach (devname, CONNECTION_SCSI, NULL);
/* return SANE_STATUS_GOOD; */
}
static void
@ -1319,6 +1527,7 @@ do_cancel (HS2P_Scanner * s)
s->scanning = SANE_FALSE;
s->cancelled = SANE_TRUE;
s->EOM = SANE_FALSE;
if (s->fd >= 0)
{
@ -1457,7 +1666,7 @@ sane_open (SANE_String_Const devnam, SANE_Handle * handle)
}
if (!dev)
{
status = attach (devnam, &dev);
status = attach (devnam, CONNECTION_SCSI, &dev);
if (status != SANE_STATUS_GOOD)
return (status);
}
@ -1550,6 +1759,285 @@ get_scan_mode_id (char *s) /* sequential search */
return scan_mode_list[i] ? i : 0;
}
#endif
SANE_Status
update_hs2p_data (HS2P_Scanner * s)
{
DBG (DBG_proc, ">> update_hs2p_data\n");
/* OPT_NREGX_ADF: */
DBG (DBG_sane_option, "OPT_NREGX_ADF\n");
s->val[OPT_NREGX_ADF].w = (SANE_Word) s->data.maintenance.nregx_adf;
/* OPT_NREGY_ADF: */
DBG (DBG_sane_option, "OPT_NREGY_ADF\n");
s->val[OPT_NREGY_ADF].w = (SANE_Word) s->data.maintenance.nregx_book;
/* OPT_NREGX_BOOK: */
DBG (DBG_sane_option, "OPT_NREGX_BOOK\n");
s->val[OPT_NREGX_BOOK].w = (SANE_Word) s->data.maintenance.nregx_book;
/* OPT_NREGY_BOOK: */
DBG (DBG_sane_option, "OPT_NREGY_BOOK\n");
s->val[OPT_NREGY_BOOK].w = (SANE_Word) s->data.maintenance.nregy_book;
/* OPT_NSCANS_ADF: */
DBG (DBG_sane_option, "OPT_NSCANS_ADF\n");
s->val[OPT_NSCANS_ADF].w =
(SANE_Word) _4btol (&(s->data.maintenance.nscans_adf[0]));
/* OPT_NSCANS_BOOK: */
DBG (DBG_sane_option, "OPT_NSCANS_BOOK\n");
s->val[OPT_NSCANS_BOOK].w =
(SANE_Word) _4btol (&(s->data.maintenance.nscans_book[0]));
/* OPT_LAMP_TIME: */
DBG (DBG_sane_option, "OPT_LAMP_TIME\n");
s->val[OPT_LAMP_TIME].w =
(SANE_Word) _4btol (&(s->data.maintenance.lamp_time[0]));
/* OPT_EO_ODD: */
DBG (DBG_sane_option, "OPT_EO_ODD\n");
s->val[OPT_EO_ODD].w = (SANE_Word) s->data.maintenance.eo_odd;
/* OPT_EO_EVEN: */
DBG (DBG_sane_option, "OPT_EO_EVEN\n");
s->val[OPT_EO_EVEN].w = (SANE_Word) s->data.maintenance.eo_even;
/* OPT_BLACK_LEVEL_ODD: */
DBG (DBG_sane_option, "OPT_BLACK_LEVEL_ODD\n");
s->val[OPT_BLACK_LEVEL_ODD].w =
(SANE_Word) s->data.maintenance.black_level_odd;
/* OPT_BLACK_LEVEL_EVEN: */
DBG (DBG_sane_option, "OPT_BLACK_LEVEL_EVEN\n");
s->val[OPT_BLACK_LEVEL_EVEN].w =
(SANE_Word) s->data.maintenance.black_level_even;
/* OPT_WHITE_LEVEL_ODD: */
DBG (DBG_sane_option, "OPT_WHITE_LEVEL_ODD\n");
s->val[OPT_WHITE_LEVEL_ODD].w =
(SANE_Word) _2btol (&(s->data.maintenance.white_level_odd[0]));
/* OPT_WHITE_LEVEL_EVEN: */
DBG (DBG_sane_option, "OPT_WHITE_LEVEL_EVEN\n");
s->val[OPT_WHITE_LEVEL_EVEN].w =
(SANE_Word) _2btol (&(s->data.maintenance.white_level_even[0]));
/* OPT_FIRST_ADJ_WHITE_ODD: */
DBG (DBG_sane_option, "OPT_FIRST_ADJ_WHITE_ODD\n");
s->val[OPT_FIRST_ADJ_WHITE_ODD].w =
(SANE_Word) _2btol (&(s->data.maintenance.first_adj_white_odd[0]));
/* OPT_FIRST_ADJ_WHITE_EVEN: */
DBG (DBG_sane_option, "OPT_FIRST_ADJ_WHITE_EVEN\n");
s->val[OPT_FIRST_ADJ_WHITE_EVEN].w =
(SANE_Word) _2btol (&(s->data.maintenance.first_adj_white_even[0]));
/* OPT_DENSITY: */
DBG (DBG_sane_option, "OPT_DENSITY\n");
s->val[OPT_DENSITY].w = (SANE_Word) s->data.maintenance.density_adj;
/* OPT_NREGX_REVERSE: */
DBG (DBG_sane_option, "OPT_NREGX_REVERSE\n");
s->val[OPT_NREGX_REVERSE].w = (SANE_Word) s->data.maintenance.nregx_reverse;
/* OPT_NREGY_REVERSE: */
DBG (DBG_sane_option, "OPT_NREGY_REVERSE\n");
s->val[OPT_NREGY_REVERSE].w = (SANE_Word) s->data.maintenance.nregy_reverse;
/* OPT_NSCANS_REVERSE_ADF: */
DBG (DBG_sane_option, "OPT_NSCANS_REVERSE_ADF\n");
s->val[OPT_NSCANS_REVERSE_ADF].w =
(SANE_Word) _4btol (&(s->data.maintenance.nscans_reverse_adf[0]));
/* OPT_REVERSE_TIME: */
DBG (DBG_sane_option, "OPT_REVERSE_TIME\n");
s->val[OPT_REVERSE_TIME].w =
(SANE_Word) _4btol (&(s->data.maintenance.reverse_time[0]));
/* OPT_NCHARS: */
DBG (DBG_sane_option, "OPT_NCHARS\n");
s->val[OPT_NCHARS].w =
(SANE_Word) _4btol (&(s->data.maintenance.nchars[0]));
DBG (DBG_proc, "<< update_hs2p_data\n");
return SANE_STATUS_GOOD;
}
static SANE_Status
hs2p_open (HS2P_Scanner * s)
{
SANE_Status status;
DBG (DBG_proc, ">> hs2p_open\n");
DBG (DBG_info, ">> hs2p_open: trying to open: name=\"%s\" fd=%d\n",
s->hw->sane.name, s->fd);
if ((status =
sanei_scsi_open (s->hw->sane.name, &s->fd, &sense_handler,
&(s->hw->sense_data))) != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sane_start: open of %s failed: %d %s\n",
s->hw->sane.name, status, sane_strstatus (status));
return (status);
}
DBG (DBG_info, ">>hs2p_open: OPENED \"%s\" fd=%d\n", s->hw->sane.name,
s->fd);
if ((status = test_unit_ready (s->fd)) != SANE_STATUS_GOOD)
{
DBG (DBG_error, "hs2p_open: test_unit_ready() failed: %s\n",
sane_strstatus (status));
sanei_scsi_close (s->fd);
s->fd = -1;
return status;
}
DBG (DBG_proc, "<< hs2p_open\n");
}
static SANE_Status
hs2p_close (HS2P_Scanner * s)
{
DBG (DBG_proc, ">> hs2p_close\n");
release_unit (s->fd);
sanei_scsi_close (s->fd);
s->fd = -1;
DBG (DBG_proc, "<< hs2p_close\n");
return SANE_STATUS_GOOD;
}
#include <stdarg.h>
static SANE_Status
get_hs2p_data (HS2P_Scanner * s, ...)
{
SANE_Status status;
SANE_Byte *buf;
size_t *len = &(s->data.bufsize);
int dtc, fd = s->fd;
u_long dtq = 0; /* two bytes */
va_list ap;
DBG (DBG_proc, ">> get_hs2p_data\n");
if (fd < 0)
{
status = hs2p_open (s);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "get_hs2p_data: error opening scanner: %s\n",
sane_strstatus (status));
return status;
}
}
for (va_start (ap, s), dtc = va_arg (ap, int); dtc != DATA_TYPE_EOL;
dtc = va_arg (ap, int))
{
DBG (DBG_proc, ">> get_hs2p_data 0x%2.2x\n", (int) dtc);
switch (dtc)
{
case DATA_TYPE_GAMMA:
buf = &(s->data.gamma[0]);
*len = sizeof (s->data.gamma);
break;
case DATA_TYPE_ENDORSER:
buf = &(s->data.endorser[0]);
*len = sizeof (s->data.endorser);
break;
case DATA_TYPE_SIZE:
buf = &(s->data.size);
*len = sizeof (s->data.size);
break;
case DATA_TYPE_PAGE_LEN:
buf = s->data.nlines;
*len = sizeof (s->data.nlines);
break;
case DATA_TYPE_MAINTENANCE:
buf = (SANE_Byte *) & (s->data.maintenance);
*len = sizeof (s->data.maintenance);
break;
case DATA_TYPE_ADF_STATUS:
buf = &(s->data.adf_status);
*len = sizeof (s->data.adf_status);
break;
case DATA_TYPE_IMAGE:
case DATA_TYPE_HALFTONE:
default:
DBG (DBG_info, "Data Type Code %2.2x not handled.\n", dtc);
return SANE_STATUS_INVAL;
}
DBG (DBG_info,
"get_hs2p_data calling read_data for dtc=%2.2x and bufsize=%lu\n",
(int) dtc, (u_long) * len);
status = read_data (s->fd, buf, len, (SANE_Byte) dtc, dtq);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "get_scanner_data: ERROR %s\n",
sane_strstatus (status));
}
}
va_end (ap);
if (fd < 0)
{ /* need to return fd to original state */
status = hs2p_close (s);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_error, "get_hs2p_data: error closing fd: %s\n",
sane_strstatus (status));
}
}
DBG (DBG_proc, "<< get_hs2p_data: %d\n", status);
return (status);
}
static SANE_Status
print_maintenance_data (MAINTENANCE_DATA * d)
{
DBG (DBG_proc, ">> print_maintenance_data: \n");
DBG (DBG_LEVEL, "nregx_adf = %d\n", d->nregx_adf);
DBG (DBG_LEVEL, "nregy_adf = %d\n", d->nregy_adf);
DBG (DBG_LEVEL, "nregx_book = %d\n", d->nregx_book);
DBG (DBG_LEVEL, "nregy_book = %d\n", d->nregy_book);
DBG (DBG_LEVEL, "nscans_adf = %lu\n", _4btol (&(d->nscans_adf[0])));
DBG (DBG_LEVEL, "nscans_adf = %lu\n", _4btol (&(d->nscans_adf[0])));
DBG (DBG_LEVEL, "lamp time = %lu\n", _4btol (&(d->lamp_time[0])));
DBG (DBG_LEVEL, "eo_odd = %d\n", d->eo_odd);
DBG (DBG_LEVEL, "eo_even = %d\n", d->eo_even);
DBG (DBG_LEVEL, "black_level_odd = %d\n", d->black_level_odd);
DBG (DBG_LEVEL, "black_level_even = %d\n", d->black_level_even);
DBG (DBG_LEVEL, "white_level_odd = %lu\n",
_2btol (&(d->white_level_odd[0])));
DBG (DBG_LEVEL, "white_level_even = %lu\n",
_2btol (&(d->white_level_even[0])));
DBG (DBG_LEVEL, "first_adj_white_odd = %lu\n",
_2btol (&(d->first_adj_white_odd[0])));
DBG (DBG_LEVEL, "first_adj_white_even = %lu\n",
_2btol (&(d->first_adj_white_even[0])));
DBG (DBG_LEVEL, "density_adj = %d\n", d->density_adj);
DBG (DBG_LEVEL, "nregx_reverse = %d\n", d->nregx_reverse);
DBG (DBG_LEVEL, "nregy_reverse = %d\n", d->nregy_reverse);
DBG (DBG_LEVEL, "nscans_reverse_adf = %lu\n",
_4btol (&(d->nscans_reverse_adf[0])));
DBG (DBG_LEVEL, "reverse_time = %lu\n", _4btol (&(d->reverse_time[0])));
DBG (DBG_LEVEL, "nchars = %lu\n", _4btol (&(d->nchars[0])));
DBG (DBG_proc, "<< print_maintenance_data: \n");
return SANE_STATUS_GOOD;
}
SANE_Status
sane_control_option (SANE_Handle handle, SANE_Int option,
@ -1559,6 +2047,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
SANE_Status status;
SANE_Word cap;
SANE_String_Const name;
SANE_Int paper_id;
@ -1620,6 +2109,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
/* case OPT_SECTION: */
case OPT_INQUIRY:
case OPT_SCAN_SOURCE:
case OPT_PAGE_ORIENTATION:
case OPT_PAPER_SIZE:
case OPT_SCAN_MODE:
case OPT_ENDORSER_STRING:
@ -1644,6 +2134,109 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
memcpy (val, s->val[option].wa, s->opt[option].size);
return SANE_STATUS_GOOD;
/* MAINTENANCE DATA */
case OPT_DATA_GROUP:
case OPT_UPDATE:
return SANE_STATUS_GOOD;
case OPT_NREGX_ADF:
DBG (DBG_sane_option, "OPT_NREGX_ADF\n");
*(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregx_adf;
return SANE_STATUS_GOOD;
case OPT_NREGY_ADF:
DBG (DBG_sane_option, "OPT_NREGY_ADF\n");
*(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregx_book;
return SANE_STATUS_GOOD;
case OPT_NREGX_BOOK:
DBG (DBG_sane_option, "OPT_NREGX_BOOK\n");
*(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregx_book;
return SANE_STATUS_GOOD;
case OPT_NREGY_BOOK:
DBG (DBG_sane_option, "OPT_NREGY_BOOK\n");
*(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregy_book;
return SANE_STATUS_GOOD;
case OPT_NSCANS_ADF:
DBG (DBG_sane_option, "OPT_NSCANS_ADF\n");
*(SANE_Word *) val =
(SANE_Word) _4btol (&(s->data.maintenance.nscans_adf[0]));
return SANE_STATUS_GOOD;
case OPT_NSCANS_BOOK:
DBG (DBG_sane_option, "OPT_NSCANS_BOOK\n");
*(SANE_Word *) val =
(SANE_Word) _4btol (&(s->data.maintenance.nscans_book[0]));
return SANE_STATUS_GOOD;
case OPT_LAMP_TIME:
DBG (DBG_sane_option, "OPT_LAMP_TIME\n");
*(SANE_Word *) val =
(SANE_Word) _4btol (&(s->data.maintenance.lamp_time[0]));
return SANE_STATUS_GOOD;
case OPT_EO_ODD:
DBG (DBG_sane_option, "OPT_EO_ODD\n");
*(SANE_Word *) val = (SANE_Word) s->data.maintenance.eo_odd;
return SANE_STATUS_GOOD;
case OPT_EO_EVEN:
DBG (DBG_sane_option, "OPT_EO_EVEN\n");
*(SANE_Word *) val = (SANE_Word) s->data.maintenance.eo_even;
return SANE_STATUS_GOOD;
case OPT_BLACK_LEVEL_ODD:
DBG (DBG_sane_option, "OPT_BLACK_LEVEL_ODD\n");
*(SANE_Word *) val =
(SANE_Word) s->data.maintenance.black_level_odd;
return SANE_STATUS_GOOD;
case OPT_BLACK_LEVEL_EVEN:
DBG (DBG_sane_option, "OPT_BLACK_LEVEL_EVEN\n");
*(SANE_Word *) val =
(SANE_Word) s->data.maintenance.black_level_even;
return SANE_STATUS_GOOD;
case OPT_WHITE_LEVEL_ODD:
DBG (DBG_sane_option, "OPT_WHITE_LEVEL_ODD\n");
*(SANE_Word *) val =
(SANE_Word) _2btol (&(s->data.maintenance.white_level_odd[0]));
return SANE_STATUS_GOOD;
case OPT_WHITE_LEVEL_EVEN:
DBG (DBG_sane_option, "OPT_WHITE_LEVEL_EVEN\n");
*(SANE_Word *) val =
(SANE_Word) _2btol (&(s->data.maintenance.white_level_even[0]));
return SANE_STATUS_GOOD;
case OPT_FIRST_ADJ_WHITE_ODD:
DBG (DBG_sane_option, "OPT_FIRST_ADJ_WHITE_ODD\n");
*(SANE_Word *) val =
(SANE_Word)
_2btol (&(s->data.maintenance.first_adj_white_odd[0]));
return SANE_STATUS_GOOD;
case OPT_FIRST_ADJ_WHITE_EVEN:
DBG (DBG_sane_option, "OPT_FIRST_ADJ_WHITE_EVEN\n");
*(SANE_Word *) val =
(SANE_Word)
_2btol (&(s->data.maintenance.first_adj_white_even[0]));
return SANE_STATUS_GOOD;
case OPT_DENSITY:
DBG (DBG_sane_option, "OPT_DENSITY\n");
*(SANE_Word *) val = (SANE_Word) s->data.maintenance.density_adj;
return SANE_STATUS_GOOD;
case OPT_NREGX_REVERSE:
DBG (DBG_sane_option, "OPT_NREGX_REVERSE\n");
*(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregx_reverse;
return SANE_STATUS_GOOD;
case OPT_NREGY_REVERSE:
DBG (DBG_sane_option, "OPT_NREGY_REVERSE\n");
*(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregy_reverse;
return SANE_STATUS_GOOD;
case OPT_NSCANS_REVERSE_ADF:
DBG (DBG_sane_option, "OPT_NSCANS_REVERSE_ADF\n");
*(SANE_Word *) val =
(SANE_Word) _4btol (&(s->data.maintenance.nscans_reverse_adf[0]));
return SANE_STATUS_GOOD;
case OPT_REVERSE_TIME:
DBG (DBG_sane_option, "OPT_REVERSE_TIME\n");
*(SANE_Word *) val =
(SANE_Word) _4btol (&(s->data.maintenance.reverse_time[0]));
return SANE_STATUS_GOOD;
case OPT_NCHARS:
DBG (DBG_sane_option, "OPT_NCHARS\n");
*(SANE_Word *) val =
(SANE_Word) _4btol (&(s->data.maintenance.nchars[0]));
return (SANE_STATUS_GOOD);
default:
DBG (DBG_proc, "sane_control_option:invalid option number %d\n",
option);
@ -1668,6 +2261,11 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
DBG (DBG_proc, "sane_control_option: set_value %s [#%d] to %s\n",
name, option, (char *) val);
break;
case SANE_TYPE_BUTTON:
DBG (DBG_proc, "sane_control_option: set_value %s [#%d]\n",
name, option);
update_hs2p_data (s);
break;
default:
DBG (DBG_proc, "sane_control_option: set_value %s [#%d]\n", name,
option);
@ -1880,20 +2478,32 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
}
return SANE_STATUS_GOOD;
case OPT_PAGE_ORIENTATION:
if (strcmp (s->val[option].s, (SANE_String) val))
{
free (s->val[option].s);
s->val[option].s = strdup (val);
if (info)
*info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
}
/* set val to current selected paper size */
paper_id = get_paper_id ((SANE_String) s->val[OPT_PAPER_SIZE].s);
goto paper_id;
case OPT_PAPER_SIZE:
/* a string option */
/* changes geometry options, therefore _RELOAD_PARAMS and _RELOAD_OPTIONS */
s->opt[OPT_AUTO_SIZE].cap |= SANE_CAP_INACTIVE; /* disable auto size */
if (strcmp (s->val[option].s, (SANE_String) val))
{
SANE_Int paper_id = get_paper_id ((SANE_String) val);
paper_id = get_paper_id ((SANE_String) val);
/* paper_id 0 is a special case (custom) that
* disables the paper size control of geometry
*/
paper_id:
if (paper_id != 0)
{
double x_max, y_max, x, y;
double x_max, y_max, x, y, temp;
x_max = SANE_UNFIX (s->hw->info.x_range.max);
y_max = SANE_UNFIX (s->hw->info.y_range.max);
@ -1908,6 +2518,16 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
*info |=
SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
if (!strcmp (s->val[OPT_PAGE_ORIENTATION].s, LANDSCAPE)) /* swap */
{
temp = y_max;
y_max = x_max;
x_max = temp;
temp = y;
y = x;
x = temp;
}
s->val[OPT_TL_X].w = SANE_FIX (0.0);
s->val[OPT_TL_Y].w = SANE_FIX (0.0);
s->val[OPT_BR_X].w = SANE_FIX (MIN (x, x_max));
@ -1916,6 +2536,26 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
free (s->val[option].s);
s->val[option].s = strdup (val);
}
return SANE_STATUS_GOOD;
case OPT_UPDATE: /* SANE_TYPE_BUTTON */
DBG (DBG_info,
"OPT_UPDATE: ready to call get_hs2p_data: fd=%d\n", s->fd);
get_hs2p_data (s,
/* DATA_TYPE_GAMMA, */
/* DATA_TYPE_ENDORSER, */
/* DATA_TYPE_SIZE, */
/* DATA_TYPE_PAGE_LEN, */
DATA_TYPE_MAINTENANCE,
/* DATA_TYPE_ADF_STATUS, */
/* DATA_TYPE_IMAGE, */
/* DATA_TYPE_HALFTONE, */
DATA_TYPE_EOL); /* va_list end */
update_hs2p_data (s);
if (DBG_LEVEL >= DBG_info)
print_maintenance_data (&(s->data.maintenance));
if (info)
*info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
return SANE_STATUS_GOOD;
}
return (SANE_STATUS_GOOD);
}
@ -2039,7 +2679,6 @@ set_window_data (HS2P_Scanner * s, SWD * wbuf)
length = (long) SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w); /* Window Length */
DBG (DBG_info, "set_window_data: WxL= %ld x %ld\n", width, length);
/* NOTE: the width in inches converted to byte unit must be the following values or less
* Binary: 620 bytes
* 4-bits gray: 2480 bytes
@ -2262,7 +2901,7 @@ sane_start (SANE_Handle handle) /* begin scanning */
SANE_Status status;
SWD wbuf; /* Set Window Data: hdr + data */
GWD gbuf; /* Get Window Data: hdr + data */
SANE_Byte mode, prefeed, adf_status, mwt = 0;
SANE_Byte mode, prefeed, mwt = 0;
DBG (DBG_proc, ">> sane_start\n");
s->cancelled = SANE_FALSE;
@ -2300,8 +2939,8 @@ sane_start (SANE_Handle handle) /* begin scanning */
DBG (DBG_info, ">> sane_start: trying to open: name=\"%s\" fd=%d\n",
s->hw->sane.name, s->fd);
if ((status =
sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler,
NULL)) != SANE_STATUS_GOOD)
sanei_scsi_open (s->hw->sane.name, &s->fd, &sense_handler,
&(s->hw->sense_data))) != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sane_start: open of %s failed: %d %s\n",
s->hw->sane.name, status, sane_strstatus (status));
@ -2476,20 +3115,23 @@ sane_start (SANE_Handle handle) /* begin scanning */
/* DONE WITH SETTING UP SCANNER ONCE PER BATCH */
s->EOM = SANE_FALSE;
if (mode != FLATBED)
{
if ((status = read_adf_status (s->fd, &adf_status)) != SANE_STATUS_GOOD)
if ((status =
get_hs2p_data (s, DATA_TYPE_ADF_STATUS,
DATA_TYPE_EOL)) != SANE_STATUS_GOOD)
{
DBG (DBG_error, "sane_start: error with read_adf_status: %s\n",
DBG (DBG_error, "sane_start: error reading adf_status: %s\n",
sane_strstatus (status));
return (status);
}
if ((adf_status & 0x00) == 0x01)
if ((s->data.adf_status & 0x00) == 0x01)
{
DBG (DBG_warning, "sane_start: No document on ADF\n");
return (SANE_STATUS_NO_DOCS);
}
else if ((adf_status & 0x02) == 0x02)
else if ((s->data.adf_status & 0x02) == 0x02)
{
DBG (DBG_warning, "sane_start: ADF cover open!\n");
return (SANE_STATUS_COVER_OPEN);
@ -2535,7 +3177,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
{
HS2P_Scanner *s = handle;
SANE_Status status;
size_t nread, bytes_requested, i;
size_t nread, bytes_requested, i, start;
SANE_Byte color;
DBG (DBG_proc, ">> sane_read\n");
@ -2574,18 +3216,20 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
if (nread > s->bytes_to_read)
nread = s->bytes_to_read;
bytes_requested = nread;
start = 0;
DBG (DBG_info, "sane_read: read %ld bytes\n", (u_long) nread);
status = read_data (s->fd, buf, &nread);
switch (status)
pad:
if (s->EOM)
{
case SANE_STATUS_NO_DOCS:
DBG (DBG_error, "sane_read: End-Of-Medium detected\n");
if (s->val[OPT_PADDING].w)
{
DBG (DBG_info, "sane_read s->EOM padding from %ld to %ld\n",
(u_long) start, (ulong) bytes_requested);
color = (s->val[OPT_NEGATIVE].w) ? 0 : 255;
for (i = nread; i < bytes_requested; i++)
/* pad to requested length */
for (i = start; i < bytes_requested; i++)
buf[i] = color;
nread = bytes_requested; /* we've padded to bytes_requested */
*len = nread;
s->bytes_to_read -= nread;
}
@ -2594,15 +3238,37 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
*len = nread;
s->bytes_to_read = 0; /* EOM */
}
break;
case SANE_STATUS_GOOD:
*len = nread;
s->bytes_to_read -= nread;
break;
default:
DBG (DBG_error, "sane_read: read error\n");
do_cancel (s);
return (SANE_STATUS_IO_ERROR);
}
else
{
DBG (DBG_info, "sane_read: trying to read %ld bytes\n", (u_long) nread);
status = read_data (s->fd, buf, &nread, DATA_TYPE_IMAGE, DTQ);
switch (status)
{
case SANE_STATUS_NO_DOCS:
DBG (DBG_error, "sane_read: End-Of-Medium detected\n");
s->EOM = SANE_TRUE;
/*
* If status != SANE_STATUS_GOOD, then sense_handler() has already
* been called and the sanei_* functions have already gotten the
* sense data buffer (which apparently clears the error conditionn)
* so the following doesn't work:
get_sense_data (s->fd, &(s->hw->sense_data));
print_sense_data (&(s->hw->sense_data));
*/
start = (isset_ILI (s->hw->sense_data)) ? /* Invalid Length Indicator */
bytes_requested - _4btol (s->hw->sense_data.information) : nread;
goto pad;
break;
case SANE_STATUS_GOOD:
*len = nread;
s->bytes_to_read -= nread;
break;
default:
DBG (DBG_error, "sane_read: read error\n");
do_cancel (s);
return (SANE_STATUS_IO_ERROR);
}
}
DBG (DBG_proc, "<< sane_read\n");
return (SANE_STATUS_GOOD);

Wyświetl plik

@ -72,8 +72,35 @@ typedef struct
const char *model;
} HS2P_HWEntry;
enum CONNECTION_TYPES
{ CONNECTION_SCSI = 0, CONNECTION_USB };
enum media
{ FLATBED = 0x00, SIMPLEX, DUPLEX };
typedef struct data
{
size_t bufsize;
/* 00H IMAGE */
/* 01H RESERVED */
/* 02H Halftone Mask */
SANE_Byte gamma[256]; /* 03H Gamma Function */
/* 04H - 7FH Reserved */
SANE_Byte endorser[19]; /* 80H Endorser */
SANE_Byte size; /* 81H startpos(4bits) + width(4bits) */
/* 82H Reserved */
/* 83H Reserved (Vendor Unique) */
SANE_Byte nlines[5]; /* 84H Page Length */
MAINTENANCE_DATA maintenance; /* 85H */
SANE_Byte adf_status; /* 86H */
/* 87H Reserved (Skew Data) */
/* 88H-91H Reserved (Vendor Unique) */
/* 92H Reserved (Scanner Extension I/O Access) */
/* 93H Reserved (Vendor Unique) */
/* 94H-FFH Reserved (Vendor Unique) */
} HS2P_DATA;
typedef struct
{
SANE_Range xres_range;
@ -210,8 +237,13 @@ typedef struct
typedef struct HS2P_Device
{
struct HS2P_Device *next;
/*
* struct with pointers to device/vendor/model names, and a type value
* used to inform sane frontend about the device
*/
SANE_Device sane;
HS2P_Info info;
SENSE_DATA sense_data;
} HS2P_Device;
#define GAMMA_LENGTH 256
@ -221,6 +253,12 @@ typedef struct HS2P_Scanner
struct HS2P_Scanner *next; /* linked list for housekeeping */
int fd; /* SCSI filedescriptor */
/* --------------------------------------------------------------------- */
/* immutable values which are set during reading of config file. */
int buffer_size; /* for sanei_open */
int connection; /* hardware interface type */
/* SANE option descriptors and values */
SANE_Option_Descriptor opt[NUM_OPTIONS];
Option_Value val[NUM_OPTIONS];
@ -245,6 +283,9 @@ typedef struct HS2P_Scanner
/*SANE_Bool backpage; */
SANE_Bool scanning;
SANE_Bool another_side;
SANE_Bool EOM;
HS2P_DATA data;
} HS2P_Scanner;
static const SANE_Range u8_range = {
@ -301,6 +342,14 @@ static const HS2P_Paper paper_sizes[] = { /* Name, Width, Height in mm */
{"Full", 0.0, 0.0},
};
#define PORTRAIT "Portait"
#define LANDSCAPE "Landscape"
static SANE_String_Const orientation_list[] = {
PORTRAIT,
LANDSCAPE,
NULL /* sentinel */
};
/* MUST be kept in sync with paper_sizes */
static SANE_String_Const paper_list[] = {
"Custom",
@ -377,11 +426,10 @@ _4btol (SANE_Byte * bytes)
static inline SANE_Int
_2btol(SANE_Byte *bytes)
{
SANE_Int rv;
SANE_Int rv;
rv = (bytes[0] << 8) |
bytes[1];
return (rv);
rv = (bytes[0] << 8) | bytes[1];
return (rv);
}
*/
static inline SANE_Int
@ -461,5 +509,8 @@ enum adf_ret_bytes
#define get_service_mode(fd) (service_mode( (fd), 0, GET ))
#define set_service_mode(fd,val) (service_mode( (fd), (val), SET ))
#define isset_ILI(sd) ( ((sd).sense_key & 0x20) != 0)
#define isset_EOM(sd) ( ((sd).sense_key & 0x40) != 0)
#endif /* HS2P_H */