diff -r -N -u sane-backends-1.0.19.orig/backend/hs2p-saneopts.h sane-backends-1.0.19/backend/hs2p-saneopts.h --- sane-backends-1.0.19.orig/backend/hs2p-saneopts.h 2008-01-02 21:42:31.000000000 -0500 +++ sane-backends-1.0.19/backend/hs2p-saneopts.h 2009-01-05 18:34:12.000000000 -0500 @@ -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 @@ /*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 @@ 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; diff -r -N -u sane-backends-1.0.19.orig/backend/hs2p-scsi.c sane-backends-1.0.19/backend/hs2p-scsi.c --- sane-backends-1.0.19.orig/backend/hs2p-scsi.c 2008-01-02 21:42:31.000000000 -0500 +++ sane-backends-1.0.19/backend/hs2p-scsi.c 2009-01-05 18:34:08.000000000 -0500 @@ -322,23 +322,67 @@ 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"); - cmd[0] = HS2P_SCSI_REQUEST_SENSE; + static SANE_Byte cmd[6]; + size_t len; + + len = sizeof (*sense_data); + memset (sense_data, 0, len); memset (cmd, 0, sizeof (cmd)); - status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); - DBG (DBG_proc, "<< request_sense\n"); + cmd[0] = HS2P_SCSI_REQUEST_SENSE; + cmd[4] = len; + + 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 @@ 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); + + 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: result=%#x, sense=%#x, asc=%#x, ascq=%#x\n", - result[0], sense, asc, ascq); + 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 @@ } 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 @@ SANE_Status status = SANE_STATUS_GOOD; return (status); } +#endif +#if 0 static SANE_Status read_maintenance_data (int fd) { @@ -1421,6 +1487,9 @@ * Bit2: reserved * Bits7-3: reserved */ + + +#if 0 static SANE_Status read_adf_status (int fd, SANE_Byte * adf_status_byte) { @@ -1440,10 +1509,10 @@ { 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 diff -r -N -u sane-backends-1.0.19.orig/backend/hs2p-scsi.h sane-backends-1.0.19/backend/hs2p-scsi.h --- sane-backends-1.0.19.orig/backend/hs2p-scsi.h 2008-01-02 21:42:31.000000000 -0500 +++ sane-backends-1.0.19/backend/hs2p-scsi.h 2009-01-05 18:34:12.000000000 -0500 @@ -217,7 +217,7 @@ {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 @@ 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 @@ /* 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 @@ * 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; diff -r -N -u sane-backends-1.0.19.orig/backend/hs2p.c sane-backends-1.0.19/backend/hs2p.c --- sane-backends-1.0.19.orig/backend/hs2p.c 2008-01-02 21:42:31.000000000 -0500 +++ sane-backends-1.0.19/backend/hs2p.c 2009-01-05 18:34:08.000000000 -0500 @@ -341,13 +341,23 @@ 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 @@ 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 @@ } } 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 @@ 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 @@ s->scanning = SANE_FALSE; s->cancelled = SANE_TRUE; + s->EOM = SANE_FALSE; if (s->fd >= 0) { @@ -1358,14 +1567,14 @@ /*DBG (DBG_sane_init, "> sane_init (authorize = %p)\n", (void *) authorize); */ #if defined PACKAGE && defined VERSION DBG (DBG_sane_init, "> sane_init: hs2p backend version %d.%d-%d (" - PACKAGE " " VERSION ")\n", V_MAJOR, V_MINOR, BUILD); + PACKAGE " " VERSION ")\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD); #endif /* sanei_thread_init (); */ if (version_code) - *version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, 0); + *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); if ((fp = sanei_config_open (HS2P_CONFIG_FILE)) != NULL) @@ -1457,7 +1666,7 @@ } if (!dev) { - status = attach (devnam, &dev); + status = attach (devnam, CONNECTION_SCSI, &dev); if (status != SANE_STATUS_GOOD) return (status); } @@ -1550,6 +1759,285 @@ 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 +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_Status status; SANE_Word cap; SANE_String_Const name; + SANE_Int paper_id; @@ -1620,6 +2109,7 @@ /* 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 @@ 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 @@ 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 @@ } 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 @@ *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 @@ 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 @@ 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_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 @@ 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 @@ /* 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 @@ { 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 @@ 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 @@ *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); diff -r -N -u sane-backends-1.0.19.orig/backend/hs2p.h sane-backends-1.0.19/backend/hs2p.h --- sane-backends-1.0.19.orig/backend/hs2p.h 2008-01-02 21:42:31.000000000 -0500 +++ sane-backends-1.0.19/backend/hs2p.h 2009-01-05 18:34:12.000000000 -0500 @@ -72,8 +72,35 @@ 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 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 @@ 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 @@ /*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 @@ {"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 @@ 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 @@ #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 */ diff -r -N -u sane-backends-1.0.19.orig/doc/descriptions/hs2p.desc sane-backends-1.0.19/doc/descriptions/hs2p.desc --- sane-backends-1.0.19.orig/doc/descriptions/hs2p.desc 2008-01-07 04:41:55.000000000 -0500 +++ sane-backends-1.0.19/doc/descriptions/hs2p.desc 2008-05-15 22:31:57.000000000 -0400 @@ -11,7 +11,6 @@ :backend "hs2p" ; name of backend :url "http://www.acjlaw.net:8080/~jeremy/Ricoh/" :version "1.00" ; version of backend -:new :yes ; :manpage "sane-hs2p" ; name of manpage (if it exists) :comment "This backend has been tested with the IS450DE (Duplex/Endorser). All major functions necessary for scanning are supported. This backend should work with all Ricoh scanners in the IS450 family as well as the IS420 series, but the IS420 has not yet been tested. Features provided by the optional Image Processing Unit (IPU) are not yet integrated into the backend, as my scanner lacks the IPU." diff -r -N -u sane-backends-1.0.19.orig/doc/sane-hs2p.man sane-backends-1.0.19/doc/sane-hs2p.man --- sane-backends-1.0.19.orig/doc/sane-hs2p.man 2008-01-02 21:42:32.000000000 -0500 +++ sane-backends-1.0.19/doc/sane-hs2p.man 2008-07-14 06:49:05.000000000 -0400 @@ -1,14 +1,14 @@ -.TH sane-hs2p 5 "01 Nov 2007" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" -.IX sane-hs2p +.TH sane\-hs2p 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" +.IX sane\-hs2p .SH NAME -sane-hs2p \- SANE backend for Ricoh SCSI flatbed/ADF scanners +sane\-hs2p \- SANE backend for Ricoh SCSI flatbed/ADF scanners .SH DESCRIPTION The -.B sane-hs2p +.B sane\-hs2p library implements a SANE (Scanner Access Now Easy) backend that provides access to the Ricoh IS450 family of scanners. Should also work with the IS420, IS410, and IS430 scanners, but these are untested. -Please contact the maintainer or the sane-devel mailing list if you own such a scanner. +Please contact the maintainer or the sane\-devel mailing list if you own such a scanner. .PP This backend is alpha-quality. It may have bugs and some scanners haven't been tested at all. Be careful and pull the plug if the scanner causes unusual @@ -25,13 +25,13 @@ .I special is either the path-name for the special device that corresponds to a SCSI scanner. The program -.I sane-find-scanner +.I sane\-find\-scanner helps to find out the correct device. Under Linux, such a device name could be .I /dev/sg0 or .IR /dev/sga , for example. See -.BR sane-scsi (5) +.BR sane\-scsi (5) for details. .SH CONFIGURATION @@ -40,7 +40,7 @@ file is a list of device names that correspond to SCSI scanners. Empty lines and lines starting with a hash mark (#) are ignored. See -.BR sane-scsi (5) +.BR sane\-scsi (5) on details of what constitutes a valid device name. .SH FILES @@ -50,10 +50,10 @@ .B SANE_CONFIG_DIR below). .TP -.I @LIBDIR@/libsane-hs2p.a +.I @LIBDIR@/libsane\-hs2p.a The static library implementing this backend. .TP -.I @LIBDIR@/libsane-hs2p.so +.I @LIBDIR@/libsane\-hs2p.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT @@ -111,8 +111,8 @@ .SH "SEE ALSO" .BR sane (7), -.BR sane-find-scanner (1), -.BR sane-scsi (5), +.BR sane\-find\-scanner (1), +.BR sane\-scsi (5), .SH AUTHOR jeremy