From b94f799b28ddfdaecfa74b83738d6f4e7151eb6b Mon Sep 17 00:00:00 2001 From: Peter Kirchgessner Date: Tue, 4 Sep 2001 13:51:11 +0000 Subject: [PATCH] - add support for active XPA - check if paper in ADF for ADF scan - add option lamp off - remove some really unused parameters --- backend/hp-device.c | 43 ++++++--- backend/hp-device.h | 2 + backend/hp-handle.c | 98 ++++++++++++++++---- backend/hp-option.c | 221 ++++++++++++++++++++++++++++++++++++++++---- backend/hp-option.h | 17 +++- backend/hp-scl.c | 53 ++++++++++- backend/hp-scl.h | 2 + backend/hp.c | 10 +- backend/hp.h | 5 + 9 files changed, 401 insertions(+), 50 deletions(-) diff --git a/backend/hp-device.c b/backend/hp-device.c index 308eee2c7..2c468bda2 100644 --- a/backend/hp-device.c +++ b/backend/hp-device.c @@ -223,27 +223,29 @@ sanei_hp_device_support_probe (HpScsi scsi) } SANE_Status -sanei_hp_device_probe (enum hp_device_compat_e *compat, HpScsi scsi) +sanei_hp_device_probe_model (enum hp_device_compat_e *compat, HpScsi scsi, + int *model_num) { static struct { HpScl cmd; + int model_num; const char * model; enum hp_device_compat_e flag; } probes[] = { - { SCL_HP_MODEL_1, "ScanJet Plus", HP_COMPAT_PLUS }, - { SCL_HP_MODEL_2, "ScanJet IIc", HP_COMPAT_2C }, - { SCL_HP_MODEL_3, "ScanJet IIp", HP_COMPAT_2P }, - { SCL_HP_MODEL_4, "ScanJet IIcx", HP_COMPAT_2CX }, - { SCL_HP_MODEL_5, "ScanJet 3c/4c/6100C", HP_COMPAT_4C }, - { SCL_HP_MODEL_6, "ScanJet 3p", HP_COMPAT_3P }, - { SCL_HP_MODEL_8, "ScanJet 4p", HP_COMPAT_4P }, - { SCL_HP_MODEL_9, "ScanJet 5p/4100C/5100C", HP_COMPAT_5P }, - { SCL_HP_MODEL_10,"PhotoSmart Photo Scanner", HP_COMPAT_PS }, - { SCL_HP_MODEL_11,"OfficeJet 1150C", HP_COMPAT_OJ_1150C }, - { SCL_HP_MODEL_12,"OfficeJet 1170C or later", HP_COMPAT_OJ_1170C }, - { SCL_HP_MODEL_14,"ScanJet 6200C/6250C", HP_COMPAT_6200C }, - { SCL_HP_MODEL_16,"ScanJet 5200C", HP_COMPAT_5200C }, - { SCL_HP_MODEL_17,"ScanJet 6300C/6350C", HP_COMPAT_6300C } + { SCL_HP_MODEL_1, 1, "ScanJet Plus", HP_COMPAT_PLUS }, + { SCL_HP_MODEL_2, 2, "ScanJet IIc", HP_COMPAT_2C }, + { SCL_HP_MODEL_3, 3, "ScanJet IIp", HP_COMPAT_2P }, + { SCL_HP_MODEL_4, 4, "ScanJet IIcx", HP_COMPAT_2CX }, + { SCL_HP_MODEL_5, 5, "ScanJet 3c/4c/6100C", HP_COMPAT_4C }, + { SCL_HP_MODEL_6, 6, "ScanJet 3p", HP_COMPAT_3P }, + { SCL_HP_MODEL_8, 8, "ScanJet 4p", HP_COMPAT_4P }, + { SCL_HP_MODEL_9, 9, "ScanJet 5p/4100C/5100C", HP_COMPAT_5P }, + { SCL_HP_MODEL_10,10,"PhotoSmart Photo Scanner", HP_COMPAT_PS }, + { SCL_HP_MODEL_11,11,"OfficeJet 1150C", HP_COMPAT_OJ_1150C }, + { SCL_HP_MODEL_12,12,"OfficeJet 1170C or later", HP_COMPAT_OJ_1170C }, + { SCL_HP_MODEL_14,14,"ScanJet 6200C/6250C", HP_COMPAT_6200C }, + { SCL_HP_MODEL_16,15,"ScanJet 5200C", HP_COMPAT_5200C }, + { SCL_HP_MODEL_17,17,"ScanJet 6300C/6350C", HP_COMPAT_6300C } }; int i; char buf[8]; @@ -251,6 +253,7 @@ sanei_hp_device_probe (enum hp_device_compat_e *compat, HpScsi scsi) SANE_Status status; static char *last_device = NULL; static enum hp_device_compat_e last_compat; + static int last_model_num = -1; assert(scsi); DBG(1, "probe_scanner: Probing %s\n", sanei_hp_scsi_devicename (scsi)); @@ -261,12 +264,14 @@ sanei_hp_device_probe (enum hp_device_compat_e *compat, HpScsi scsi) { DBG(3, "probe_scanner: use cached compatibility flags\n"); *compat = last_compat; + if (model_num) *model_num = last_model_num; return SANE_STATUS_GOOD; } sanei_hp_free (last_device); last_device = NULL; } *compat = 0; + last_model_num = -1; for (i = 0; i < (int)(sizeof(probes)/sizeof(probes[0])); i++) { DBG(1,"probing %s\n",probes[i].model); @@ -277,6 +282,7 @@ sanei_hp_device_probe (enum hp_device_compat_e *compat, HpScsi scsi) { DBG(1, "probe_scanner: %s compatible\n", probes[i].model); *compat |= probes[i].flag; + last_model_num = probes[i].model_num; } else if (!UNSUPPORTED( status )) return status; /* SCL inquiry failed */ @@ -284,10 +290,17 @@ sanei_hp_device_probe (enum hp_device_compat_e *compat, HpScsi scsi) /* Save values for next call */ last_device = sanei_hp_strdup (sanei_hp_scsi_devicename (scsi)); last_compat = *compat; + if (model_num) *model_num = last_model_num; return SANE_STATUS_GOOD; } +SANE_Status +sanei_hp_device_probe (enum hp_device_compat_e *compat, HpScsi scsi) +{ + return sanei_hp_device_probe_model (compat, scsi, 0); +} + hp_bool_t sanei_hp_device_compat (HpDevice this, enum hp_device_compat_e which) { diff --git a/backend/hp-device.h b/backend/hp-device.h index 549dcbcdd..d5e85cd48 100644 --- a/backend/hp-device.h +++ b/backend/hp-device.h @@ -82,6 +82,8 @@ SANE_Status sanei_hp_device_simulate_set (const char *devname, HpScl scl, SANE_Status sanei_hp_device_support_get (const char *devname, HpScl scl, int *minval, int *maxval); SANE_Status sanei_hp_device_support_probe (HpScsi scsi); +SANE_Status sanei_hp_device_probe_model (enum hp_device_compat_e *compat, + HpScsi scsi, int *model_num); SANE_Status sanei_hp_device_probe (enum hp_device_compat_e *compat, HpScsi scsi); hp_bool_t sanei_hp_device_compat (HpDevice this, diff --git a/backend/hp-handle.c b/backend/hp-handle.c index eb4825fcd..2a0acc96a 100644 --- a/backend/hp-handle.c +++ b/backend/hp-handle.c @@ -57,7 +57,7 @@ extern int sanei_debug_hp; */ #include #include -#include "hp.h" +#include "hp-handle.h" #include "sane/sanei_backend.h" @@ -165,7 +165,6 @@ hp_handle_stopScan (HpHandle this) */ sanei_hp_scl_reset(scsi); } - sanei_hp_scl_set(scsi, SCL_LAMPTEST, 0); /* Switch off lamp */ sanei_hp_scsi_destroy(scsi,0); } } @@ -425,12 +424,23 @@ sanei_hp_handle_startScan (HpHandle this) /* For ADF scan we should check if there is paper available */ if ( adfscan ) {int adfstat = 0; + int can_check_paper = 0; + int is_flatbed = 0; int minval, maxval; - /* HP ScanJet IIp does not support commands ADF scan window */ - /* and unload document. We have to use the usual scan window. */ - /* It turned out that other scanners also do not support unload */ - /* document, but change document (which is not supported by IIp too) */ + /* For ADF-support, we have three different types of scanners: + * ScanJet, ScanJet+, IIp, 3p: + * scroll feed, no support for inquire paper in ADF, unload document + * and preload document + * IIc, IIcx, 3c, 4c, 6100C, 4p: + * flatbed, no support for preload document + * 5100C, 5200C, 6200C, 6300C: + * scroll feed. + * For all scroll feed types, we use the usual scan window command. + * For flatbed types, use a sequence of special commands. + */ + + /* Check the IIp group */ if ( (sanei_hp_device_support_get (this->dev->sanedev.name, SCL_UNLOAD, &minval, &maxval) != SANE_STATUS_GOOD ) @@ -438,12 +448,37 @@ sanei_hp_handle_startScan (HpHandle this) SCL_CHANGE_DOC, &minval, &maxval) != SANE_STATUS_GOOD ) ) { - - DBG(1, "start: Request for ADF scan without support of unload doc\n"); - DBG(1, " and change doc. Seems to be a IIp.\n"); - DBG(1, " Use standard scan window command.\n"); + DBG(3, "start: Request for ADF scan without support of unload doc\n"); + DBG(3, " and change doc. Seems to be something like a IIp.\n"); + DBG(3, " Use standard scan window command.\n"); scl = SCL_START_SCAN; + can_check_paper = 0; + is_flatbed = 0; + } +/* + else if ( sanei_hp_device_support_get (this->dev->sanedev.name, + SCL_PRELOAD_ADF, &minval, &maxval) + != SANE_STATUS_GOOD ) +*/ + else if ( sanei_hp_is_flatbed_adf (scsi) ) + { + DBG(3, "start: Request for ADF scan without support of preload doc.\n"); + DBG(3, " Seems to be a flatbed ADF.\n"); + DBG(3, " Use ADF scan window command.\n"); + + can_check_paper = 1; + is_flatbed = 1; + } + else + { + DBG(3, "start: Request for ADF scan with support of preload doc.\n"); + DBG(3, " Seems to be a scroll feed ADF.\n"); + DBG(3, " Use standard scan window command.\n"); + + scl = SCL_START_SCAN; + can_check_paper = 1; + is_flatbed = 0; } /* Check if the ADF is ready */ @@ -457,10 +492,39 @@ sanei_hp_handle_startScan (HpHandle this) if ( adfstat != 1 ) { - DBG(1, "start: ADF scan requested without paper. Finished.\n"); + DBG(1, "start: ADF is not ready. Finished.\n"); sanei_hp_scsi_destroy(scsi,0); return SANE_STATUS_NO_DOCS; } + + /* Check paper in ADF */ + if ( can_check_paper ) + { + if ( sanei_hp_scl_inquire(scsi, SCL_ADF_BIN, &adfstat, 0, 0) + != SANE_STATUS_GOOD ) + { + DBG(1, "start: Error checking if paper in ADF\n"); + sanei_hp_scsi_destroy(scsi,0); + return SANE_STATUS_UNSUPPORTED; + } + + if ( adfstat != 1 ) + { + DBG(1, "start: No paper in ADF bin. Finished.\n"); + sanei_hp_scsi_destroy(scsi,0); + return SANE_STATUS_NO_DOCS; + } + + if ( is_flatbed ) + { + if ( sanei_hp_scl_set(scsi, SCL_CHANGE_DOC, 0) != SANE_STATUS_GOOD ) + { + DBG(1, "start: Error changing document\n"); + sanei_hp_scsi_destroy(scsi,0); + return SANE_STATUS_UNSUPPORTED; + } + } + } } DBG(1, "start: %s to mirror image vertically\n", procdata.mirror_vertical ? @@ -482,7 +546,7 @@ sanei_hp_handle_startScan (HpHandle this) procdata.lines = this->scan_params.lines; /* Wait for front-panel button push ? */ - status = sanei_hp_optset_start_wait(this->dev->options, this->data, scsi); + status = sanei_hp_optset_start_wait(this->dev->options, this->data); if (status) /* Wait for front button push ? Start scan in reader process */ { @@ -565,11 +629,13 @@ sanei_hp_handle_read (HpHandle this, void * buf, size_t *lengthp) if ( sanei_hp_scsi_new(&scsi, this->dev->sanedev.name) == SANE_STATUS_GOOD ) { - sanei_hp_scl_set(scsi, SCL_LAMPTEST, 0); - hpinfo = sanei_hp_device_info_get ( this->dev->sanedev.name ); - if ( hpinfo && hpinfo->unload_after_scan ) - sanei_hp_scl_set(scsi, SCL_UNLOAD, 0); + + if ( hpinfo ) + { + if ( hpinfo->unload_after_scan ) + sanei_hp_scl_set(scsi, SCL_UNLOAD, 0); + } sanei_hp_scsi_destroy(scsi,0); } diff --git a/backend/hp-option.c b/backend/hp-option.c index 6d7981ff9..b7a968293 100644 --- a/backend/hp-option.c +++ b/backend/hp-option.c @@ -1398,6 +1398,7 @@ _probe_geometry (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { HpScl scl = this->descriptor->scl_command; hp_bool_t is_tl = 0; + hp_bool_t active_xpa = sanei_hp_is_active_xpa ( scsi ); int minval, maxval; SANE_Fixed fval; @@ -1445,6 +1446,14 @@ _probe_geometry (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data) return SANE_STATUS_NO_MEM; } + /* The active xpa is only 5x5 inches */ + if ( (!is_tl) && active_xpa + && (sanei_hp_optset_scan_type (optset, data) == SCL_XPA_SCAN) ) + { + DBG(3,"Set maxval to 1500 because of active XPA\n"); + maxval = 1500; + } + fval = is_tl ? SANE_FIX(0.0) : maxval * SANE_FIX(MM_PER_DEVPIX); RETURN_IF_FAIL( sanei_hp_accessor_set(this->data_acsr, data, &fval) ); @@ -1797,6 +1806,47 @@ _program_generic (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) return hp_option_download(this, data, optset, scsi); } +static SANE_Status +_program_geometry (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) +{ +/* #define HP_LIMIT_ADF_WINDOW */ +#ifndef HP_LIMIT_ADF_WINDOW + + return hp_option_download(this, data, optset, scsi); + +#else + + HpScl scl = this->descriptor->scl_command; + int value; + SANE_Status Status; + + if (sanei_hp_optset_scan_type (optset, data) != SCL_ADF_SCAN) + return hp_option_download(this, data, optset, scsi); + + /* ADF may crash when scanning only a window ? */ + if ( (scl == SCL_X_POS) || (scl == SCL_Y_POS) ) + { + value = 0; + DBG(3,"program_geometry: set %c-pos to %d\n", + (scl == SCL_X_POS) ? 'x' : 'y', value); + } + else if ( scl == SCL_X_EXTENT ) + { + value = 2550; + DBG(3,"program_geometry: set x-extent to %d\n", value); + } + else + { + value = 4200; + DBG(3,"program_geometry: set y-extent to %d\n", value); + } + + Status = sanei_hp_scl_set(scsi, scl, value); + return Status; + +#endif +} + static SANE_Status _program_data_width (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { @@ -1805,7 +1855,14 @@ _program_data_width (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) SANE_Status status; if ( sanei_hp_optset_scanmode (optset, data) == HP_SCANMODE_COLOR ) + { value *= 3; + if (value < 24) + { + DBG(3,"program_data_width: map datawith from %d to 24\n", (int)value); + value = 24; + } + } status = sanei_hp_scl_set(scsi, scl, value); return status; } @@ -2259,10 +2316,99 @@ _program_unload_after_scan (HpOption this, HpScsi scsi, HpOptSet optset, return SANE_STATUS_GOOD; } +static SANE_Status +_program_lamp_off (HpOption this, HpScsi scsi, HpOptSet optset, + HpData data) +{ + DBG(3,"program_lamp_off: shut off lamp\n"); + + return sanei_hp_scl_set(scsi, SCL_LAMPTEST, 0); +} + static SANE_Status _program_scan_type (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) -{ +{ int req_scan_type, val, minval, maxval, current_scan_type; + + req_scan_type = sanei_hp_accessor_getint(this->data_acsr, data); + + if ( req_scan_type == HP_SCANTYPE_XPA ) + { + enum hp_scanmode_e scan_mode = sanei_hp_optset_scanmode(optset, data); + static unsigned char xpa_matrix_coeff[] = { +0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x80 + }; + static unsigned char xpa_tone_map[] = { +0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xfe,0x0f, +0xe1,0x0f,0xd3,0x0f,0xc4,0x0f,0xb5,0x0f,0xa6,0x0f,0x97,0x0f,0x88,0x0f,0x79,0x0f, +0x6a,0x0f,0x5b,0x0f,0x4b,0x0f,0x3c,0x0f,0x2c,0x0f,0x1d,0x0f,0x0d,0x0e,0xfe,0x0e, +0xee,0x0e,0xde,0x0e,0xce,0x0e,0xbe,0x0e,0xae,0x0e,0x9e,0x0e,0x8e,0x0e,0x7d,0x0e, +0x6d,0x0e,0x5c,0x0e,0x4c,0x0e,0x3b,0x0e,0x2a,0x0e,0x19,0x0e,0x08,0x0d,0xf7,0x0d, +0xe6,0x0d,0xd5,0x0d,0xc4,0x0d,0xb2,0x0d,0xa1,0x0d,0x8f,0x0d,0x7d,0x0d,0x6b,0x0d, +0x59,0x0d,0x47,0x0d,0x35,0x0d,0x22,0x0d,0x10,0x0c,0xfd,0x0c,0xeb,0x0c,0xd8,0x0c, +0xc5,0x0c,0xb2,0x0c,0x9e,0x0c,0x8b,0x0c,0x77,0x0c,0x64,0x0c,0x50,0x0c,0x3c,0x0c, +0x28,0x0c,0x14,0x0b,0xff,0x0b,0xeb,0x0b,0xd6,0x0b,0xc1,0x0b,0xac,0x0b,0x96,0x0b, +0x81,0x0b,0x6b,0x0b,0x55,0x0b,0x3f,0x0b,0x29,0x0b,0x12,0x0a,0xfc,0x0a,0xe5,0x0a, +0xce,0x0a,0xb6,0x0a,0x9e,0x0a,0x87,0x0a,0x6e,0x0a,0x56,0x0a,0x3d,0x0a,0x24,0x0a, +0x0b,0x09,0xf1,0x09,0xd8,0x09,0xbd,0x09,0xa3,0x09,0x88,0x09,0x6d,0x09,0x51,0x09, +0x35,0x09,0x19,0x08,0xfc,0x08,0xdf,0x08,0xc1,0x08,0xa3,0x08,0x84,0x08,0x65,0x08, +0x45,0x08,0x24,0x08,0x03,0x07,0xe1,0x07,0xbe,0x07,0x9b,0x07,0x78,0x07,0x53,0x07, +0x2d,0x07,0x07,0x06,0xdf,0x06,0xb7,0x06,0x8d,0x06,0x62,0x06,0x36,0x06,0x07,0x05, +0xd8,0x05,0xa6,0x05,0x72,0x05,0x3c,0x04,0xfc,0x04,0x7c,0x03,0xfc,0x03,0x7c,0x02, +0xfc,0x02,0x7c,0x01,0xfc,0x01,0x7c,0x00,0xfc,0x00,0x7c,0x00,0x00,0x0f,0xfe,0x0f, +0xe1,0x0f,0xd3,0x0f,0xc4,0x0f,0xb5,0x0f,0xa6,0x0f,0x97,0x0f,0x88,0x0f,0x79,0x0f, +0x6a,0x0f,0x5b,0x0f,0x4b,0x0f,0x3c,0x0f,0x2c,0x0f,0x1d,0x0f,0x0d,0x0e,0xfe,0x0e, +0xee,0x0e,0xde,0x0e,0xce,0x0e,0xbe,0x0e,0xae,0x0e,0x9e,0x0e,0x8e,0x0e,0x7d,0x0e, +0x6d,0x0e,0x5c,0x0e,0x4c,0x0e,0x3b,0x0e,0x2a,0x0e,0x19,0x0e,0x08,0x0d,0xf7,0x0d, +0xe6,0x0d,0xd5,0x0d,0xc4,0x0d,0xb2,0x0d,0xa1,0x0d,0x8f,0x0d,0x7d,0x0d,0x6b,0x0d, +0x59,0x0d,0x47,0x0d,0x35,0x0d,0x22,0x0d,0x10,0x0c,0xfd,0x0c,0xeb,0x0c,0xd8,0x0c, +0xc5,0x0c,0xb2,0x0c,0x9e,0x0c,0x8b,0x0c,0x77,0x0c,0x64,0x0c,0x50,0x0c,0x3c,0x0c, +0x28,0x0c,0x14,0x0b,0xff,0x0b,0xeb,0x0b,0xd6,0x0b,0xc1,0x0b,0xac,0x0b,0x96,0x0b, +0x81,0x0b,0x6b,0x0b,0x55,0x0b,0x3f,0x0b,0x29,0x0b,0x12,0x0a,0xfc,0x0a,0xe5,0x0a, +0xce,0x0a,0xb6,0x0a,0x9e,0x0a,0x87,0x0a,0x6e,0x0a,0x56,0x0a,0x3d,0x0a,0x24,0x0a, +0x0b,0x09,0xf1,0x09,0xd8,0x09,0xbd,0x09,0xa3,0x09,0x88,0x09,0x6d,0x09,0x51,0x09, +0x35,0x09,0x19,0x08,0xfc,0x08,0xdf,0x08,0xc1,0x08,0xa3,0x08,0x84,0x08,0x65,0x08, +0x45,0x08,0x24,0x08,0x03,0x07,0xe1,0x07,0xbe,0x07,0x9b,0x07,0x78,0x07,0x53,0x07, +0x2d,0x07,0x07,0x06,0xdf,0x06,0xb7,0x06,0x8d,0x06,0x62,0x06,0x36,0x06,0x07,0x05, +0xd8,0x05,0xa6,0x05,0x72,0x05,0x3c,0x04,0xfc,0x04,0x7c,0x03,0xfc,0x03,0x7c,0x02, +0xfc,0x02,0x7c,0x01,0xfc,0x01,0x7c,0x00,0xfc,0x00,0x7c,0x00,0x00,0x0f,0xfe,0x0f, +0xe1,0x0f,0xd3,0x0f,0xc4,0x0f,0xb5,0x0f,0xa6,0x0f,0x97,0x0f,0x88,0x0f,0x79,0x0f, +0x6a,0x0f,0x5b,0x0f,0x4b,0x0f,0x3c,0x0f,0x2c,0x0f,0x1d,0x0f,0x0d,0x0e,0xfe,0x0e, +0xee,0x0e,0xde,0x0e,0xce,0x0e,0xbe,0x0e,0xae,0x0e,0x9e,0x0e,0x8e,0x0e,0x7d,0x0e, +0x6d,0x0e,0x5c,0x0e,0x4c,0x0e,0x3b,0x0e,0x2a,0x0e,0x19,0x0e,0x08,0x0d,0xf7,0x0d, +0xe6,0x0d,0xd5,0x0d,0xc4,0x0d,0xb2,0x0d,0xa1,0x0d,0x8f,0x0d,0x7d,0x0d,0x6b,0x0d, +0x59,0x0d,0x47,0x0d,0x35,0x0d,0x22,0x0d,0x10,0x0c,0xfd,0x0c,0xeb,0x0c,0xd8,0x0c, +0xc5,0x0c,0xb2,0x0c,0x9e,0x0c,0x8b,0x0c,0x77,0x0c,0x64,0x0c,0x50,0x0c,0x3c,0x0c, +0x28,0x0c,0x14,0x0b,0xff,0x0b,0xeb,0x0b,0xd6,0x0b,0xc1,0x0b,0xac,0x0b,0x96,0x0b, +0x81,0x0b,0x6b,0x0b,0x55,0x0b,0x3f,0x0b,0x29,0x0b,0x12,0x0a,0xfc,0x0a,0xe5,0x0a, +0xce,0x0a,0xb6,0x0a,0x9e,0x0a,0x87,0x0a,0x6e,0x0a,0x56,0x0a,0x3d,0x0a,0x24,0x0a, +0x0b,0x09,0xf1,0x09,0xd8,0x09,0xbd,0x09,0xa3,0x09,0x88,0x09,0x6d,0x09,0x51,0x09, +0x35,0x09,0x19,0x08,0xfc,0x08,0xdf,0x08,0xc1,0x08,0xa3,0x08,0x84,0x08,0x65,0x08, +0x45,0x08,0x24,0x08,0x03,0x07,0xe1,0x07,0xbe,0x07,0x9b,0x07,0x78,0x07,0x53,0x07, +0x2d,0x07,0x07,0x06,0xdf,0x06,0xb7,0x06,0x8d,0x06,0x62,0x06,0x36,0x06,0x07,0x05, +0xd8,0x05,0xa6,0x05,0x72,0x05,0x3c,0x04,0xfc,0x04,0x7c,0x03,0xfc,0x03,0x7c,0x02, +0xfc,0x02,0x7c,0x01,0xfc,0x01,0x7c,0x00,0xfc,0x00,0x7c,0x00,0x00 + }; + + sanei_hp_scl_set(scsi, SCL_RESERVED1, 0); /* dont know */ + sanei_hp_scl_set(scsi, SCL_10952, 0); /* Calibration mode */ + + if ( sanei_hp_is_active_xpa (scsi) + && ( (scan_mode==HP_SCANMODE_COLOR) + || (scan_mode==HP_SCANMODE_GRAYSCALE)) ) + { + DBG (3,"program_scan_type: set tone map for active XPA\n"); + sanei_hp_scl_download (scsi, SCL_10x9MATRIX_COEFF, xpa_matrix_coeff, + sizeof (xpa_matrix_coeff)); + sanei_hp_scl_set(scsi, SCL_MATRIX, -1); /* Set matrix coefficient */ + + sanei_hp_scl_download (scsi, SCL_7x12TONE_MAP, xpa_tone_map, + sizeof (xpa_tone_map)); + sanei_hp_scl_set(scsi, SCL_TONE_MAP, -1); /* Select tone map */ + } + } + return SANE_STATUS_GOOD; } @@ -2408,6 +2554,13 @@ _program_scanmode (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { enum hp_scanmode_e new_mode = hp_option_getint(this, data); int invert = 0; + hp_bool_t disable_xpa = ( sanei_hp_optset_scan_type (optset, data) + != SCL_XPA_SCAN ); + + /* Disbaling XPA resets some settings in the scanner. */ + /* Scanmode is the first we program. So set XPA prior to scanmode */ + DBG(3, "program_scanmode: disable XPA = %d\n", (int)disable_xpa); + sanei_hp_scl_set(scsi, SCL_XPA_DISABLE, disable_xpa); RETURN_IF_FAIL( hp_option_download(this, data, optset, scsi) ); @@ -2415,9 +2568,13 @@ _program_scanmode (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) case HP_SCANMODE_GRAYSCALE: RETURN_IF_FAIL( sanei_hp_scl_set(scsi, SCL_DATA_WIDTH, 8) ); invert = 1; + /* For active XPA we use a tone map. Dont invert */ + if ( (!disable_xpa) && sanei_hp_is_active_xpa (scsi) ) invert = 0; break; case HP_SCANMODE_COLOR: invert = 1; + /* For active XPA we use a tone map. Dont invert */ + if ( (!disable_xpa) && sanei_hp_is_active_xpa (scsi) ) invert = 0; break; default: break; @@ -3025,9 +3182,9 @@ static const struct hp_option_descriptor_s PS_EXPOSURE_TIME[1] = {{ /* global settings. The user should switch to ADF scanning after */ /* placing paper in the ADF. */ static const struct hp_choice_s _scan_types[] = { - { 0, "Normal", 0, 0, 0 }, - {1, "ADF", 0, 0, 0 }, - {2, "XPA", 0, 0, 0 }, + { HP_SCANTYPE_NORMAL, "Normal", 0, 0, 0 }, + { HP_SCANTYPE_ADF, "ADF", 0, 0, 0 }, + { HP_SCANTYPE_XPA, "XPA", 0, 0, 0 }, {0, 0, 0, 0, 0 } }; @@ -3035,7 +3192,7 @@ static const struct hp_option_descriptor_s SCAN_SOURCE[1] = {{ SCANNER_OPTION(SCAN_SOURCE, STRING, NONE), NO_REQUIRES, _probe_scan_type, _program_scan_type, 0, - 1, 1, 0, 0, 0, SCL_START_SCAN, 0, 0, 0, _scan_types + 1, 1, 1, 0, 0, SCL_START_SCAN, 0, 0, 0, _scan_types }}; /* Unload after is only necessary for PhotoScanner */ @@ -3064,8 +3221,7 @@ static const struct hp_option_descriptor_s UNLOAD[1] = {{ /* So here we need the requiries. */ static const struct hp_option_descriptor_s CALIBRATE[1] = {{ SCANNER_OPTION(CALIBRATE, BUTTON, NONE), - REQUIRES(HP_COMPAT_2CX | HP_COMPAT_4C | HP_COMPAT_4P | HP_COMPAT_5P - | HP_COMPAT_PS | HP_COMPAT_5100C | HP_COMPAT_6200C), + REQUIRES(HP_COMPAT_PS), _probe_calibrate, _program_calibrate, _enable_calibrate, 0, 0, 1, 1, 0, SCL_CALIBRATE, 0, 0, 0, 0 }}; @@ -3077,25 +3233,25 @@ static const struct hp_option_descriptor_s GEOMETRY_GROUP[1] = {{ static const struct hp_option_descriptor_s SCAN_TL_X[1] = {{ SCANNER_OPTION(SCAN_TL_X, FIXED, MM), NO_REQUIRES, - _probe_geometry, _program_generic, 0, + _probe_geometry, _program_geometry, 0, 0, 1, 0, 0, 1, SCL_X_POS, 0, 0, 0, 0 }}; static const struct hp_option_descriptor_s SCAN_TL_Y[1] = {{ SCANNER_OPTION(SCAN_TL_Y, FIXED, MM), NO_REQUIRES, - _probe_geometry, _program_generic, 0, + _probe_geometry, _program_geometry, 0, 0, 1, 0, 0, 1, SCL_Y_POS, 0, 0, 0, 0 }}; static const struct hp_option_descriptor_s SCAN_BR_X[1] = {{ SCANNER_OPTION(SCAN_BR_X, FIXED, MM), NO_REQUIRES, - _probe_geometry, _program_generic, 0, + _probe_geometry, _program_geometry, 0, 0, 1, 0, 0, 1, SCL_X_EXTENT, 0, 0, 0, 0 }}; static const struct hp_option_descriptor_s SCAN_BR_Y[1] = {{ SCANNER_OPTION(SCAN_BR_Y, FIXED, MM), NO_REQUIRES, - _probe_geometry, _program_generic, 0, + _probe_geometry, _program_geometry, 0, 0, 1, 0, 0, 1, SCL_Y_EXTENT, 0, 0, 0, 0 }}; @@ -3146,6 +3302,32 @@ static const struct hp_option_descriptor_s BUTTON_WAIT[1] = } }; + +static const struct hp_option_descriptor_s LAMP_OFF[1] = +{ + { + SCANNER_OPTION(LAMP_OFF, BUTTON, NONE), + /* Lamp off instruction not supported by Photosmart */ + REQUIRES( HP_COMPAT_PLUS | HP_COMPAT_2C | HP_COMPAT_2P | HP_COMPAT_2CX + | HP_COMPAT_4C | HP_COMPAT_3P | HP_COMPAT_4P | HP_COMPAT_5P + | HP_COMPAT_5100C | HP_COMPAT_6200C | HP_COMPAT_5200C + | HP_COMPAT_6300C), /* enum hp_device_compat_e requires */ + _probe_bool, /* SANE_Status (*probe)() */ + _program_lamp_off, /* SANE_Status (*program)() */ + 0, /* hp_bool_t (*enable)() */ + 0, /* hp_bool_t has_global_effect */ + 0, /* hp_bool_t affects_scan_params */ + 1, /* hp_bool_t program_immediate */ + 1, /* hp_bool_t suppress_for_scan */ + 0, /* hp_bool_t may_change */ + SCL_LAMPTEST, /* HpScl scl_command */ + 0, /* int minval */ + 0, /* int maxval */ + 0, /* int startval */ + 0 /* HpChoice choices */ + } +}; + #ifdef HP_EXPERIMENTAL static const struct hp_choice_s _range_choices[] = { @@ -3230,7 +3412,7 @@ static HpOptionDescriptor hp_options[] = { HALFTONE_PATTERN_8x8, HORIZONTAL_DITHER_8x8, SCAN_SPEED, SMOOTHING, MEDIA, PS_EXPOSURE_TIME, BIT_DEPTH, OUT8, - SCAN_SOURCE, BUTTON_WAIT, UNLOAD_AFTER_SCAN, + SCAN_SOURCE, BUTTON_WAIT, LAMP_OFF, UNLOAD_AFTER_SCAN, CHANGE_DOC, UNLOAD, CALIBRATE, GEOMETRY_GROUP, @@ -3392,7 +3574,7 @@ sanei_hp_optset_mirror_vert (HpOptSet this, HpData data, HpScsi scsi) return mirror == HP_MIRROR_VERT_ON; } -hp_bool_t sanei_hp_optset_start_wait(HpOptSet this, HpData data, HpScsi scsi) +hp_bool_t sanei_hp_optset_start_wait(HpOptSet this, HpData data) { HpOption mode; int wait; @@ -3451,7 +3633,7 @@ hp_optset_add (HpOptSet this, HpOption opt) } static SANE_Status -hp_optset_fix_geometry_options (HpOptSet this, HpDevice dev) +hp_optset_fix_geometry_options (HpOptSet this) { _HpOption tl_x = _hp_optset_get(this, SCAN_TL_X); _HpOption tl_y = _hp_optset_get(this, SCAN_TL_Y); @@ -3567,7 +3749,14 @@ sanei_hp_optset_download (HpOptSet this, HpData data, HpScsi scsi) DBG(3, "Start downloading parameters to scanner\n"); /* Reset scanner to wake it up */ - RETURN_IF_FAIL(sanei_hp_scl_reset (scsi)); + + /* Reset would switch off XPA lamp and switch on scanner lamp. */ + /* Only do a reset if not in active XPA mode */ + if ( (sanei_hp_optset_scan_type (this, data) != SCL_XPA_SCAN) + || (!sanei_hp_is_active_xpa (scsi)) ) + { + RETURN_IF_FAIL(sanei_hp_scl_reset (scsi)); + } RETURN_IF_FAIL(sanei_hp_scl_clearErrors (scsi)); sanei_hp_device_simulate_clear ( sanei_hp_scsi_devicename (scsi) ); @@ -3675,7 +3864,7 @@ sanei_hp_optset_new(HpOptSet * newp, HpScsi scsi, HpDevice dev) this->num_sane_opts); /* Now for some kludges */ - status = hp_optset_fix_geometry_options(this, dev); + status = hp_optset_fix_geometry_options(this); if (FAILED(status)) { sanei_hp_free(this); diff --git a/backend/hp-option.h b/backend/hp-option.h index 622076749..1c34a709d 100644 --- a/backend/hp-option.h +++ b/backend/hp-option.h @@ -162,6 +162,14 @@ # define HP_BUTTON_WAIT_YES 1 #endif +#ifndef SANE_NAME_LAMP_OFF +# define SANE_NAME_LAMP_OFF "lamp-off" +# define SANE_TITLE_LAMP_OFF "Shut off lamp" +# define SANE_DESC_LAMP_OFF "Shut off scanner lamp." +# define HP_LAMP_OFF_NO 0 +# define HP_LAMP_OFF_YES 1 +#endif + /* Some test stuff to see what undocumented SCL-commands do */ # define SANE_NAME_10470 "10470" # define SANE_TITLE_10470 "10470" @@ -209,6 +217,13 @@ enum hp_scanmode_e HP_SCANMODE_COLOR = 5 }; +enum hp_scantype_e +{ + HP_SCANTYPE_NORMAL = 0, + HP_SCANTYPE_ADF = 1, + HP_SCANTYPE_XPA = 2 +}; + enum hp_dither_type_e { HP_DITHER_CUSTOM = -1, HP_DITHER_COARSE = 0, @@ -266,7 +281,7 @@ hp_bool_t sanei_hp_optset_output_8bit (HpOptSet this, HpData data); int sanei_hp_optset_data_width (HpOptSet this, HpData data); hp_bool_t sanei_hp_optset_isImmediate (HpOptSet this, int optnum); hp_bool_t sanei_hp_optset_mirror_vert (HpOptSet this, HpData data, HpScsi scsi); -hp_bool_t sanei_hp_optset_start_wait(HpOptSet this, HpData data, HpScsi scsi); +hp_bool_t sanei_hp_optset_start_wait(HpOptSet this, HpData data); HpScl sanei_hp_optset_scan_type (HpOptSet this, HpData data); const SANE_Option_Descriptor * sanei_hp_optset_saneoption (HpOptSet this, HpData data, int optnum); diff --git a/backend/hp-scl.c b/backend/hp-scl.c index be83d1598..1a310fb16 100644 --- a/backend/hp-scl.c +++ b/backend/hp-scl.c @@ -71,6 +71,7 @@ extern int sanei_debug_hp;*/ #include "hp-option.h" #include "hp-scsi.h" #include "hp-scl.h" +#include "hp-device.h" #ifdef HAVE_PTAL #include @@ -399,7 +400,7 @@ sanei_hp_nonscsi_new (HpScsi * newp, const char * devname, HpConnect connect) #endif /* For SCSI-devices we would have the inquire command here */ - strncpy (new->inq_data, "\003zzzzzzzHP MODELx R000", + strncpy ((char *)new->inq_data, "\003zzzzzzzHP MODELx R000", sizeof (new->inq_data)); new->bufp = new->buf + HP_SCSI_CMD_LEN; @@ -550,6 +551,49 @@ sanei_hp_scsi_devicename (HpScsi this) return this->devname; } +hp_bool_t +sanei_hp_is_active_xpa (HpScsi scsi) +{HpDeviceInfo *info; + int model_num; + + info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); + if (info->active_xpa < 0) + { + model_num = sanei_hp_get_max_model (scsi); + info->active_xpa = (model_num >= 17); + DBG(5,"sanei_hp_is_active_xpa: model=%d, active_xpa=%d\n", + model_num, info->active_xpa); + } + return info->active_xpa; +} + +int +sanei_hp_get_max_model (HpScsi scsi) + +{HpDeviceInfo *info; + + info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); + if (info->max_model < 0) + {enum hp_device_compat_e compat; + int model_num; + + if ( sanei_hp_device_probe_model ( &compat, scsi, &model_num) + == SANE_STATUS_GOOD ) + info->max_model = model_num; + } + return info->max_model; +} + + +int +sanei_hp_is_flatbed_adf (HpScsi scsi) + +{int model = sanei_hp_get_max_model (scsi); + + return ((model == 2) || (model == 4) || (model == 5) || (model == 8)); +} + + HpConnect sanei_hp_get_connect (const char *devname) @@ -1730,6 +1774,13 @@ sanei_hp_scl_startScan(HpScsi scsi, HpScl scl) DBG(1, "sanei_hp_scl_startScan: Start scan%s\n", msg); + /* For active XPA we must not use XPA scan */ + if ((scl == SCL_XPA_SCAN) && sanei_hp_is_active_xpa (scsi)) + { + DBG(3,"Map XPA scan to scan because of active XPA\n"); + scl = SCL_START_SCAN; + } + RETURN_IF_FAIL( hp_scsi_scl(scsi, scl, 0) ); return hp_scsi_flush(scsi); } diff --git a/backend/hp-scl.h b/backend/hp-scl.h index d11d3e49f..79544920f 100644 --- a/backend/hp-scl.h +++ b/backend/hp-scl.h @@ -73,6 +73,7 @@ #define SCL_BRIGHTNESS HP_SCL_CONTROL(10317, 'a', 'L') #define SCL_MIRROR_IMAGE HP_SCL_CONTROL(10318, 'a', 'M') #define SCL_SHARPENING HP_SCL_CONTROL(10319, 'a', 'N') +#define SCL_RESERVED1 HP_SCL_CONTROL(10320, 'a', 'O') #define SCL_X_RESOLUTION HP_SCL_CONTROL(10323, 'a', 'R') #define SCL_Y_RESOLUTION HP_SCL_CONTROL(10324, 'a', 'S') #define SCL_OUTPUT_DATA_TYPE HP_SCL_CONTROL(10325, 'a', 'T') @@ -92,6 +93,7 @@ #define SCL_SPEED HP_SCL_CONTROL(10950, 'u', 'E') #define SCL_FILTER HP_SCL_CONTROL(10951, 'u', 'F') #define SCL_10952 HP_SCL_CONTROL(10952, 'u', 'G') +#define SCL_XPA_DISABLE HP_SCL_CONTROL(10953, 'u', 'H') #define SCL_TONE_MAP HP_SCL_CONTROL(10956, 'u', 'K') #define SCL_CALIBRATE HP_SCL_COMMAND('u', 'R') #define SCL_ADF_SCAN HP_SCL_COMMAND('u', 'S') diff --git a/backend/hp.c b/backend/hp.c index 064c0f2cf..1315a6dcd 100644 --- a/backend/hp.c +++ b/backend/hp.c @@ -43,9 +43,15 @@ HP Scanner Control Language (SCL). */ -static char *hp_backend_version = "0.94"; +static char *hp_backend_version = "0.95"; /* Changes: + V 0.95, 07-Jul-2001, PK (peter@kirchgessner.net) + - add support for active XPA + - check if paper in ADF for ADF scan + - add option lamp off + - remove some really unused parameters + V 0.94, 31-Dec-2000, PK (peter@kirchgessner.net) - always switch off lamp after scan @@ -303,6 +309,8 @@ hp_device_info_create (const char *devname) k = sizeof (info->devname); strncpy (info->devname, devname, k); info->devname[k-1] = '\0'; + info->max_model = -1; + info->active_xpa = -1; return info; } diff --git a/backend/hp.h b/backend/hp.h index 015a2b500..7bdd4d58a 100644 --- a/backend/hp.h +++ b/backend/hp.h @@ -144,6 +144,8 @@ typedef struct HpSimulate simulate; /* Info about simulations */ hp_bool_t unload_after_scan; + int active_xpa; + int max_model; } HpDeviceInfo; HpDeviceInfo *sanei_hp_device_info_get (const char *dev_name); @@ -193,6 +195,9 @@ typedef struct hp_handle_s * HpHandle; typedef struct hp_scsi_s * HpScsi; /* hp-scl.c */ +hp_bool_t sanei_hp_is_active_xpa (HpScsi scsi); +int sanei_hp_get_max_model (HpScsi scsi); +int sanei_hp_is_flatbed_adf (HpScsi scsi); HpConnect sanei_hp_get_connect (const char *devname); HpConnect sanei_hp_scsi_get_connect (HpScsi this);