hp-backend V 0.91, 04-Sep-2000, David Paschal (paschal@rcsis.com):

- Added support for flatbed HP OfficeJets
      - (PK) fix problem with cancel preview

   hp-backend V 0.91, V 0.90, 02-Sep-2000, PK:
      - fix timing problem between killing child and writing to pipe
      - change fprintf(stderr,...) to DBG
      - change include <sane..> to "sane.." in hp.h
      - change handling of options that have global effects.
        i.e. if option scanmode is received (has global effect),
        all options that "may change" are send to the scanner again.
        This fixes a problem that --resolution specified infront of
        --mode on command line of scanimage was ignored.
        NOTE: This change does not allow to specify --depth 12 infront of
        --mode color, because --depth is only enabled with --mode color.
      - add depth greater 8 bits for mode grayscale
      - add option for 8 bit output but 10/12 bit scanning
DEVEL_2_0_BRANCH-1
Peter Kirchgessner 2000-09-09 17:44:14 +00:00
rodzic e56def0c53
commit e907811055
10 zmienionych plików z 774 dodań i 140 usunięć

Wyświetl plik

@ -157,6 +157,9 @@ sanei_hp_device_support_probe (HpScsi scsi)
SCL_BW_DITHER,
SCL_CONTRAST,
SCL_BRIGHTNESS,
#ifdef SCL_SHARPENING
SCL_SHARPENING,
#endif
SCL_MIRROR_IMAGE,
SCL_X_RESOLUTION,
SCL_Y_RESOLUTION,
@ -175,6 +178,7 @@ sanei_hp_device_support_probe (HpScsi scsi)
SCL_CHANGE_DOC,
SCL_ADF_BFEED
};
enum hp_device_compat_e compat;
DBG(1, "hp_device_support_probe: Check supported commands for %s\n",
sanei_hp_scsi_devicename (scsi) );
@ -194,6 +198,14 @@ sanei_hp_device_support_probe (HpScsi scsi)
sclsupport->is_supported = (status == SANE_STATUS_GOOD);
sclsupport->checked = 1;
/* The OfficeJets seem to ignore brightness and contrast settings,
* so we'll pretend they're not supported at all. */
if (((sclprobe[k]==SCL_BRIGHTNESS) || (sclprobe[k]==SCL_CONTRAST)) &&
(sanei_hp_device_probe (&compat, scsi) == SANE_STATUS_GOOD) &&
(compat & HP_COMPAT_OJ_1150C)) {
sclsupport->is_supported=0;
}
if (sclsupport->is_supported)
{
DBG(1, "hp_device_support_probe: %d supported (%d..%d, %d)\n",
@ -217,18 +229,20 @@ sanei_hp_device_probe (enum hp_device_compat_e *compat, HpScsi scsi)
const char * model;
enum hp_device_compat_e flag;
} probes[] = {
{ SCL_HP_MODEL_1, "Plus", HP_COMPAT_PLUS },
{ SCL_HP_MODEL_2, "IIc", HP_COMPAT_2C },
{ SCL_HP_MODEL_3, "IIp", HP_COMPAT_2P },
{ SCL_HP_MODEL_4, "IIcx", HP_COMPAT_2CX },
{ SCL_HP_MODEL_5, "4c/3c", HP_COMPAT_4C },
{ SCL_HP_MODEL_6, "3p", HP_COMPAT_3P },
{ SCL_HP_MODEL_8, "4P", HP_COMPAT_4P },
{ SCL_HP_MODEL_9, "5P", HP_COMPAT_5P },
{ SCL_HP_MODEL_10, "Photo Scanner", HP_COMPAT_PS },
{ SCL_HP_MODEL_14, "6200C/6250C", HP_COMPAT_6200C },
{ SCL_HP_MODEL_16, "5200C",HP_COMPAT_5200C },
{ SCL_HP_MODEL_17, "6300C/6350C",HP_COMPAT_6300C }
{ 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 }
};
int i;
char buf[8];
@ -260,7 +274,7 @@ sanei_hp_device_probe (enum hp_device_compat_e *compat, HpScsi scsi)
if (!FAILED( status = sanei_hp_scl_upload(scsi, probes[i].cmd,
buf, sizeof(buf)) ))
{
DBG(1, "probe_scanner: Scanjet %s compatible\n", probes[i].model);
DBG(1, "probe_scanner: %s compatible\n", probes[i].model);
*compat |= probes[i].flag;
}
else if (!UNSUPPORTED( status ))
@ -298,7 +312,7 @@ hp_nonscsi_device_new (HpDevice * newp, const char * devname, HpConnect connect)
|| memcmp(sanei_hp_scsi_vendor(scsi), "HP ", 8) != 0)
{
DBG(1, "%s: does not seem to be an HP scanner\n", devname);
sanei_hp_scsi_destroy(scsi);
sanei_hp_scsi_destroy(scsi,1);
return SANE_STATUS_INVAL;
}
#endif
@ -307,7 +321,7 @@ hp_nonscsi_device_new (HpDevice * newp, const char * devname, HpConnect connect)
if (FAILED( sanei_hp_scl_reset(scsi) ))
{
DBG(1, "hp_nonscsi_device_new: SCL reset failed\n");
sanei_hp_scsi_destroy(scsi);
sanei_hp_scsi_destroy(scsi,1);
return SANE_STATUS_IO_ERROR;
}
@ -334,7 +348,7 @@ hp_nonscsi_device_new (HpDevice * newp, const char * devname, HpConnect connect)
sanei_hp_device_support_probe (scsi);
status = sanei_hp_optset_new(&(this->options), scsi, this);
}
sanei_hp_scsi_destroy(scsi);
sanei_hp_scsi_destroy(scsi,1);
if (FAILED(status))
{
@ -363,6 +377,8 @@ sanei_hp_device_new (HpDevice * newp, const char * devname)
SANE_Status status;
char * str;
DBG(3, "sanei_hp_device_new: %s\n", devname);
connect = sanei_hp_get_connect (devname);
if ( connect != HP_CONNECT_SCSI )
return hp_nonscsi_device_new (newp, devname, connect);
@ -377,7 +393,7 @@ sanei_hp_device_new (HpDevice * newp, const char * devname)
|| memcmp(sanei_hp_scsi_vendor(scsi), "HP ", 8) != 0)
{
DBG(1, "%s: does not seem to be an HP scanner\n", devname);
sanei_hp_scsi_destroy(scsi);
sanei_hp_scsi_destroy(scsi,1);
return SANE_STATUS_INVAL;
}
@ -385,7 +401,7 @@ sanei_hp_device_new (HpDevice * newp, const char * devname)
if (FAILED( sanei_hp_scl_reset(scsi) ))
{
DBG(1, "sanei_hp_device_new: SCL reset failed\n");
sanei_hp_scsi_destroy(scsi);
sanei_hp_scsi_destroy(scsi,1);
return SANE_STATUS_IO_ERROR;
}
@ -412,7 +428,7 @@ sanei_hp_device_new (HpDevice * newp, const char * devname)
sanei_hp_device_support_probe (scsi);
status = sanei_hp_optset_new(&this->options, scsi, this);
}
sanei_hp_scsi_destroy(scsi);
sanei_hp_scsi_destroy(scsi,1);
if (FAILED(status))
{

Wyświetl plik

@ -47,19 +47,21 @@
#include "hp.h"
enum hp_device_compat_e {
HP_COMPAT_PLUS = 1 << 0, /* Hp ScanJet Plus */
HP_COMPAT_PLUS = 1 << 0, /* HP ScanJet Plus */
HP_COMPAT_2C = 1 << 1,
HP_COMPAT_2P = 1 << 2,
HP_COMPAT_2CX = 1 << 3,
HP_COMPAT_4C = 1 << 4, /* also for 3C, 6100C */
HP_COMPAT_4C = 1 << 4, /* also 3c, 6100C */
HP_COMPAT_3P = 1 << 5,
HP_COMPAT_4P = 1 << 6,
HP_COMPAT_5P = 1 << 7,
HP_COMPAT_5100C = 1 << 8, /* also 4100 C */
HP_COMPAT_PS = 1 << 9, /* Hp PhotoSmart Photo Scanner */
HP_COMPAT_6200C = 1 << 10,
HP_COMPAT_5200C = 1 << 11,
HP_COMPAT_6300C = 1 << 12
HP_COMPAT_5P = 1 << 7, /* also 4100C, 5100C */
HP_COMPAT_5100C = 1 << 8, /* redundant with 5p */
HP_COMPAT_PS = 1 << 9, /* HP PhotoSmart Photo Scanner */
HP_COMPAT_OJ_1150C = 1 << 10,
HP_COMPAT_OJ_1170C = 1 << 11, /* also later OfficeJets */
HP_COMPAT_6200C = 1 << 12,
HP_COMPAT_5200C = 1 << 13,
HP_COMPAT_6300C = 1 << 14
};
struct hp_device_s

Wyświetl plik

@ -130,6 +130,7 @@ hp_handle_startReader (HpHandle this, HpScsi scsi, HpProcessData *procdata)
/* not closing fds[1] gives an infinite loop on Digital UNIX */
status = sanei_hp_scsi_pipeout(scsi,fds[1],procdata);
close (fds[1]);
DBG(3,"hp_handle_startReader: Exiting child (%s)\n",sane_strstatus(status));
_exit(status);
}
@ -144,10 +145,10 @@ hp_handle_stopScan (HpHandle this)
if (this->reader_pid)
{
int info;
DBG(3, "do_cancel: killing child (%d)\n", this->reader_pid);
DBG(3, "hp_handle_stopScan: killing child (%d)\n", this->reader_pid);
kill(this->reader_pid, SIGTERM);
waitpid(this->reader_pid, &info, 0);
DBG(1, "do_cancel: child %s = %d\n",
DBG(1, "hp_handle_stopScan: child %s = %d\n",
WIFEXITED(info) ? "exited, status" : "signalled, signal",
WIFEXITED(info) ? WEXITSTATUS(info) : WTERMSIG(info));
close(this->pipefd);
@ -161,15 +162,19 @@ hp_handle_stopScan (HpHandle this)
sanei_hp_scl_errcheck(scsi);
*/
sanei_hp_scl_reset(scsi);
sanei_hp_scsi_destroy(scsi);
sanei_hp_scsi_destroy(scsi,0);
}
}
else
{
DBG(3, "hp_handle_stopScan: no pid for child\n");
}
return SANE_STATUS_GOOD;
}
static SANE_Status
hp_handle_uploadParameters (HpHandle this, HpScsi scsi, int *scan_depth,
hp_bool_t *soft_invert)
hp_bool_t *soft_invert, hp_bool_t *out8)
{
SANE_Parameters * p = &this->scan_params;
int data_width;
@ -178,6 +183,7 @@ hp_handle_uploadParameters (HpHandle this, HpScsi scsi, int *scan_depth,
assert(scsi);
*soft_invert = 0;
*out8 = 0;
p->last_frame = SANE_TRUE;
/* inquire resulting size of image after setting it up */
@ -196,17 +202,48 @@ hp_handle_uploadParameters (HpHandle this, HpScsi scsi, int *scan_depth,
p->format = SANE_FRAME_GRAY;
p->depth = 1;
*scan_depth = 1;
/* The OfficeJets don't seem to handle SCL_INVERSE_IMAGE, so we'll
* have to invert in software. */
if ((sanei_hp_device_probe (&compat, scsi) == SANE_STATUS_GOOD)
&& (compat & HP_COMPAT_OJ_1150C)) {
*soft_invert=1;
}
break;
case HP_SCANMODE_GRAYSCALE: /* Grayscale */
p->format = SANE_FRAME_GRAY;
p->depth = 8;
*scan_depth = 8;
p->depth = (data_width > 8) ? 16 : 8;
*scan_depth = data_width;
/* 8 bit output forced ? */
if ( *scan_depth > 8 )
{
*out8 = sanei_hp_optset_output_8bit (this->dev->options, this->data);
DBG(1,"hp_handle_uploadParameters: out8=%d\n", (int)*out8);
if (*out8)
{
p->depth = 8;
p->bytes_per_line /= 2;
}
}
break;
case HP_SCANMODE_COLOR: /* RGB */
p->format = SANE_FRAME_RGB;
p->depth = (data_width > 24) ? 16 : 8;
*scan_depth = data_width / 3;
/* 8 bit output forced ? */
if ( *scan_depth > 8 )
{
*out8 = sanei_hp_optset_output_8bit (this->dev->options, this->data);
DBG(1,"hp_handle_uploadParameters: out8=%d\n", (int)*out8);
if (*out8)
{
p->depth = 8;
p->bytes_per_line /= 2;
}
}
/* HP PhotoSmart does not invert when depth > 8. Lets do it by software */
if ( (*scan_depth > 8)
&& (sanei_hp_device_probe (&compat, scsi) == SANE_STATUS_GOOD)
@ -245,7 +282,17 @@ sanei_hp_handle_new (HpDevice dev)
void
sanei_hp_handle_destroy (HpHandle this)
{
HpScsi scsi=0;
DBG(3,"sanei_hp_handle_destroy: stop scan\n");
hp_handle_stopScan(this);
if (sanei_hp_scsi_new(&scsi,this->dev->sanedev.name)==SANE_STATUS_GOOD &&
scsi) {
sanei_hp_scsi_destroy(scsi,1);
}
sanei_hp_data_destroy(this->data);
sanei_hp_free(this);
}
@ -253,6 +300,11 @@ sanei_hp_handle_destroy (HpHandle this)
const SANE_Option_Descriptor *
sanei_hp_handle_saneoption (HpHandle this, SANE_Int optnum)
{
if (this->cancelled)
{
DBG(1, "sanei_hp_handle_saneoption: cancelled. Stop scan\n");
hp_handle_stopScan(this);
}
return sanei_hp_optset_saneoption(this->dev->options, this->data, optnum);
}
@ -264,10 +316,11 @@ sanei_hp_handle_control(HpHandle this, SANE_Int optnum,
HpScsi scsi;
hp_bool_t immediate;
#if 0
if (hp_handle_isScanning(this))
return SANE_STATUS_DEVICE_BUSY;
#endif
if (this->cancelled)
{
DBG(1, "sanei_hp_handle_control: cancelled. Stop scan\n");
RETURN_IF_FAIL( hp_handle_stopScan(this) );
}
if (hp_handle_isScanning(this))
return SANE_STATUS_DEVICE_BUSY;
@ -279,7 +332,7 @@ sanei_hp_handle_control(HpHandle this, SANE_Int optnum,
status = sanei_hp_optset_control(this->dev->options, this->data,
optnum, action, valp, info, scsi,
immediate);
sanei_hp_scsi_destroy ( scsi );
sanei_hp_scsi_destroy ( scsi,0 );
return status;
}
@ -292,6 +345,12 @@ sanei_hp_handle_getParameters (HpHandle this, SANE_Parameters *params)
if (!params)
return SANE_STATUS_GOOD;
if (this->cancelled)
{
DBG(1, "sanei_hp_handle_getParameters: cancelled. Stop scan\n");
RETURN_IF_FAIL( hp_handle_stopScan(this) );
}
if (hp_handle_isScanning(this))
{
*params = this->scan_params;
@ -310,7 +369,7 @@ sanei_hp_handle_getParameters (HpHandle this, SANE_Parameters *params)
if (!FAILED( sanei_hp_scsi_new(&scsi, this->dev->sanedev.name) )) {
RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, SCL_NUMBER_OF_LINES,
&p->lines,0,0));
sanei_hp_scsi_destroy(scsi);
sanei_hp_scsi_destroy(scsi,0);
*params = this->scan_params;
}
}
@ -330,7 +389,10 @@ sanei_hp_handle_startScan (HpHandle this)
/* FIXME: setup preview mode stuff? */
if (hp_handle_isScanning(this))
{
DBG(3,"sanei_hp_handle_startScan: Stop current scan\n");
RETURN_IF_FAIL( hp_handle_stopScan(this) );
}
RETURN_IF_FAIL( sanei_hp_scsi_new(&scsi, this->dev->sanedev.name) );
@ -339,11 +401,12 @@ sanei_hp_handle_startScan (HpHandle this)
if (!FAILED(status))
status = hp_handle_uploadParameters(this, scsi,
&(procdata.bits_per_channel),
&(procdata.invert));
&(procdata.invert),
&(procdata.out8));
if (FAILED(status))
{
sanei_hp_scsi_destroy(scsi);
sanei_hp_scsi_destroy(scsi,0);
return status;
}
@ -394,10 +457,16 @@ sanei_hp_handle_startScan (HpHandle this)
this->bytes_left = ( this->scan_params.bytes_per_line
* this->scan_params.lines );
DBG(1, "start: %d pixels per line, %d bytes, %d lines high\n",
DBG(1, "start: %d pixels per line, %d bytes per line, %d lines high\n",
this->scan_params.pixels_per_line, this->scan_params.bytes_per_line,
this->scan_params.lines);
procdata.bytes_per_line = (int)this->scan_params.bytes_per_line;
if (procdata.out8)
{
procdata.bytes_per_line *= 2;
DBG(1,"(scanner will send %d bytes per line, 8 bit output forced)\n",
procdata.bytes_per_line);
}
procdata.lines = this->scan_params.lines;
/* Wait for front-panel button push ? */
@ -419,7 +488,7 @@ sanei_hp_handle_startScan (HpHandle this)
status = hp_handle_startReader(this, scsi, &procdata);
}
sanei_hp_scsi_destroy(scsi);
sanei_hp_scsi_destroy(scsi,0);
return status;
}
@ -431,17 +500,18 @@ sanei_hp_handle_read (HpHandle this, void * buf, size_t *lengthp)
ssize_t nread;
SANE_Status status;
DBG(3, "read: trying to read %lu bytes\n", (unsigned long) *lengthp);
DBG(3, "sanei_hp_handle_read: trying to read %lu bytes\n",
(unsigned long) *lengthp);
if (!hp_handle_isScanning(this))
{
DBG(1, "read: not scanning\n");
DBG(1, "sanei_hp_handle_read: not scanning\n");
return SANE_STATUS_INVAL;
}
if (this->cancelled)
{
DBG(1, "read: cancelled\n");
DBG(1, "sanei_hp_handle_read: cancelled. Stop scan\n");
RETURN_IF_FAIL( hp_handle_stopScan(this) );
return SANE_STATUS_CANCELLED;
}
@ -457,7 +527,8 @@ sanei_hp_handle_read (HpHandle this, void * buf, size_t *lengthp)
*lengthp = 0;
if (errno == EAGAIN)
return SANE_STATUS_GOOD;
DBG(1, "read: read from pipe: %s\n", strerror(errno));
DBG(1, "sanei_hp_handle_read: read from pipe: %s. Stop scan\n",
strerror(errno));
hp_handle_stopScan(this);
return SANE_STATUS_IO_ERROR;
}
@ -466,11 +537,11 @@ sanei_hp_handle_read (HpHandle this, void * buf, size_t *lengthp)
if (nread > 0)
{
DBG(3, "read: read %lu bytes\n", (unsigned long) nread);
DBG(3, "sanei_hp_handle_read: read %lu bytes\n", (unsigned long) nread);
return SANE_STATUS_GOOD;
}
DBG(1, "read: EOF from pipe\n");
DBG(1, "sanei_hp_handle_read: EOF from pipe. Stop scan\n");
status = this->bytes_left ? SANE_STATUS_IO_ERROR : SANE_STATUS_EOF;
RETURN_IF_FAIL( hp_handle_stopScan(this) );
@ -486,7 +557,7 @@ sanei_hp_handle_read (HpHandle this, void * buf, size_t *lengthp)
== SANE_STATUS_GOOD )
{
sanei_hp_scl_set(scsi, SCL_UNLOAD, 0);
sanei_hp_scsi_destroy(scsi);
sanei_hp_scsi_destroy(scsi,0);
}
}
}
@ -497,6 +568,17 @@ void
sanei_hp_handle_cancel (HpHandle this)
{
this->cancelled = 1;
/* Office-Jets (K series) may not deliver enough data. */
/* Therefor the read might not return until it is interrupted. */
DBG(3,"sanei_hp_handle_cancel: compat flags: 0x%04x\n",
(int)this->dev->compat);
if ( (this->reader_pid)
&& (this->dev->compat & (HP_COMPAT_OJ_1150C | HP_COMPAT_OJ_1170C)) )
{
DBG(3,"sanei_hp_handle_cancel: send SIGTERM to child (%d)\n",
this->reader_pid);
kill(this->reader_pid, SIGTERM);
}
}
SANE_Status
@ -507,6 +589,7 @@ sanei_hp_handle_setNonblocking (HpHandle this, hp_bool_t non_blocking)
if (this->cancelled)
{
DBG(3,"sanei_hp_handle_setNonblocking: cancelled. Stop scan\n");
RETURN_IF_FAIL( hp_handle_stopScan(this) );
return SANE_STATUS_CANCELLED;
}
@ -525,6 +608,7 @@ sanei_hp_handle_getPipefd (HpHandle this, SANE_Int *fd)
if (this->cancelled)
{
DBG(3,"sanei_hp_handle_getPipefd: cancelled. Stop scan\n");
RETURN_IF_FAIL( hp_handle_stopScan(this) );
return SANE_STATUS_CANCELLED;
}

Wyświetl plik

@ -147,7 +147,6 @@ struct hp_option_descriptor_s
HpScl scl_command;
int minval, maxval, startval; /* for simulation */
HpChoice choices;
/* unsigned nchan, chan */
};
struct hp_data_info_s
@ -163,7 +162,7 @@ static const struct hp_option_descriptor_s
GAMMA_VECTOR_7x12[1],
RGB_TONEMAP[1], GAMMA_VECTOR_R[1], GAMMA_VECTOR_G[1], GAMMA_VECTOR_B[1],
#endif
HALFTONE_PATTERN[1], MEDIA[1], BIT_DEPTH[1], SCAN_SOURCE[1],
HALFTONE_PATTERN[1], MEDIA[1], OUT8[1], BIT_DEPTH[1], SCAN_SOURCE[1],
#ifdef FAKE_COLORSEP_MATRIXES
SEPMATRIX[1],
#endif
@ -517,7 +516,7 @@ hp_option_imm_set (HpOptSet optset, HpOption this, HpData data,
if (FAILED( status = sanei_constrain_value(optd, valp, info) ))
{
DBG(1, "option_set: %s: constrain_value failed :%s\n",
DBG(1, "option_imm_set: %s: constrain_value failed :%s\n",
this->descriptor->name, sane_strstatus(status));
return status;
}
@ -526,7 +525,7 @@ hp_option_imm_set (HpOptSet optset, HpOption this, HpData data,
if (_values_are_equal(this, data, old_val, valp))
{
DBG(3, "option_set: value unchanged\n");
DBG(3, "option_imm_set: value unchanged\n");
return SANE_STATUS_GOOD;
}
@ -557,6 +556,7 @@ hp_option_set (HpOption this, HpData data, void * valp, SANE_Int * info)
HpSaneOption optd = hp_option_saneoption(this, data);
hp_byte_t * old_val = alloca(optd->size);
SANE_Status status;
char sval[64];
if (!SANE_OPTION_IS_SETTABLE(optd->cap) || !this->data_acsr)
@ -564,6 +564,12 @@ hp_option_set (HpOption this, HpData data, void * valp, SANE_Int * info)
if (!old_val)
return SANE_STATUS_NO_MEM;
sval[0] = '\0';
if (this->descriptor->type == SANE_TYPE_INT)
sprintf (sval," value=%d", *(int*)valp);
DBG(10,"hp_option_set: %s%s\n", this->descriptor->name, sval);
if (FAILED( status = sanei_constrain_value(optd, valp, info) ))
{
DBG(1, "option_set: %s: constrain_value failed :%s\n",
@ -575,7 +581,7 @@ hp_option_set (HpOption this, HpData data, void * valp, SANE_Int * info)
if (_values_are_equal(this, data, old_val, valp))
{
DBG(3, "option_set: value unchanged\n");
DBG(3, "option_set: %s: value unchanged\n",this->descriptor->name);
return SANE_STATUS_GOOD;
}
@ -592,6 +598,9 @@ hp_option_set (HpOption this, HpData data, void * valp, SANE_Int * info)
*info |= SANE_INFO_RELOAD_OPTIONS;
if (this->descriptor->affects_scan_params)
*info |= SANE_INFO_RELOAD_PARAMS;
DBG(3, "option_set: %s: info=0x%lx\n",this->descriptor->name,
(long)*info);
}
return SANE_STATUS_GOOD;
@ -644,11 +653,28 @@ hp_option_control (HpOption this, HpData data,
}
}
static void
hp_option_reprogram (HpOption this, HpOptSet optset, HpData data, HpScsi scsi)
{
if (this->descriptor->may_change)
{
DBG(5, "hp_option_reprogram: %s\n", this->descriptor->name);
hp_option_program (this, scsi, optset, data);
}
}
static void
hp_option_reprobe (HpOption this, HpOptSet optset, HpData data, HpScsi scsi)
{
if (this->descriptor->may_change)
{
DBG(5, "hp_option_reprobe: %s\n", this->descriptor->name);
(*this->descriptor->probe)((_HpOption)this, scsi, optset, data);
}
}
static void
@ -701,7 +727,7 @@ _set_size (HpOption opt, HpData data, SANE_Int size)
_hp_option_saneoption(opt, data)->size = size;
}
#ifdef HP_EXPERIMENTAL
/* #ifdef HP_EXPERIMENTAL */
static SANE_Status
_probe_int (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data)
{
@ -722,7 +748,7 @@ _probe_int (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data)
_set_size(this, data, sizeof(SANE_Int));
return _set_range(this, data, minval, 1, maxval);
}
#endif
/* #endif */
static SANE_Status
_probe_int_brightness (_HpOption this, HpScsi scsi, HpOptSet optset,
@ -787,6 +813,14 @@ _probe_resolution (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data)
sanei_hp_accessor_setint(this->data_acsr, data, val);
_set_size(this, data, sizeof(SANE_Int));
/* The HP OfficeJet Pro 1150C crashes the scan head when scanning at
* resolutions less than 42 dpi. Set a safe minimum resolution.
* Hopefully 50 dpi is safe enough. */
if ((sanei_hp_device_probe(&compat,scsi)==SANE_STATUS_GOOD) &&
((compat&(HP_COMPAT_OJ_1150C|HP_COMPAT_OJ_1170C))==HP_COMPAT_OJ_1150C)) {
if (minval<50) minval=50;
}
/* HP Photosmart scanner does not allow scanning at arbitrary resolutions */
/* for slides/negatives. Must be multiple of 300 dpi. Set quantization. */
@ -824,17 +858,6 @@ _probe_bool (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data)
return SANE_STATUS_GOOD;
}
static SANE_Status
_probe_preview (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data)
{
int val = 0;
if (!(this->data_acsr = sanei_hp_accessor_bool_new(data)))
return SANE_STATUS_NO_MEM;
sanei_hp_accessor_setint(this->data_acsr, data, val);
_set_size(this, data, sizeof(SANE_Bool));
return SANE_STATUS_GOOD;
}
static SANE_Status
_probe_change_doc (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data)
@ -862,6 +885,36 @@ _probe_change_doc (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data)
return SANE_STATUS_GOOD;
}
/* The OfficeJets support SCL_UNLOAD even when no ADF is installed, so
* this function was added to check for SCL_ADF_CAPABILITY, similar to
* _probe_change_doc(), to hide the unnecessary "Unload" button on
* non-ADF OfficeJets. */
static SANE_Status
_probe_unload (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data)
{SANE_Status status;
int cap = 0;
DBG(2, "probe_unload: inquire ADF capability\n");
status = sanei_hp_scl_inquire(scsi, SCL_ADF_CAPABILITY, &cap, 0, 0);
if ( (status != SANE_STATUS_GOOD) || (cap == 0))
return SANE_STATUS_UNSUPPORTED;
DBG(2, "probe_unload: check if unload is supported\n");
status = sanei_hp_scl_inquire(scsi, SCL_UNLOAD, &cap, 0, 0);
if ( status != SANE_STATUS_GOOD )
return SANE_STATUS_UNSUPPORTED;
if (!(this->data_acsr = sanei_hp_accessor_bool_new(data)))
return SANE_STATUS_NO_MEM;
sanei_hp_accessor_setint(this->data_acsr, data, cap);
_set_size(this, data, sizeof(SANE_Bool));
return SANE_STATUS_GOOD;
}
static SANE_Status
_probe_calibrate (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data)
{
@ -871,6 +924,13 @@ _probe_calibrate (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data)
int download_calib_file = 1;
enum hp_device_compat_e compat;
/* The OfficeJets don't seem to support calibration, so we'll
* remove it from the option list to reduce frontend clutter. */
if ((sanei_hp_device_probe (&compat, scsi) == SANE_STATUS_GOOD) &&
(compat & HP_COMPAT_OJ_1150C)) {
return SANE_STATUS_UNSUPPORTED;
}
/* If we have a Photosmart scanner, we only download the calibration file */
/* when medium is set to prints */
media = -1;
@ -972,14 +1032,24 @@ _probe_choice (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data)
{
enum hp_scanmode_e scanmode = sanei_hp_optset_scanmode (optset, data);
/* Some PhotoSmart scanner report support for only 24 bit. */
/* But they also support 30 bit. Dont rely on the inquire in this case */
if ( (maxval == 24)
&& (sanei_hp_device_probe (&compat, scsi) == SANE_STATUS_GOOD)
/* The data width inquiries seem not to work properly on PhotoSmart */
/* Sometimes they report just 24 bits, but support 30 bits too. */
/* Sometimes they report min/max to be 24/8. Assume they all support */
/* at least 10 bits per channel for RGB. Grayscale is only supported */
/* with 8 bits. */
if ( (sanei_hp_device_probe (&compat, scsi) == SANE_STATUS_GOOD)
&& (compat & HP_COMPAT_PS))
{
DBG(1, "choice_option_probe: set max. datawidth to 30 for photosmart");
maxval = 30;
if (scanmode == HP_SCANMODE_GRAYSCALE)
{
minval = 8; if (maxval < 8) maxval = 8;
}
else if (scanmode == HP_SCANMODE_COLOR)
{
minval = 24; if (maxval < 30) maxval = 30;
}
DBG(1, "choice_option_probe: set max. datawidth to %d for photosmart\n",
maxval);
}
if ( scanmode == HP_SCANMODE_COLOR )
@ -988,6 +1058,15 @@ _probe_choice (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data)
maxval /= 3; if ( maxval <= 0) maxval = 1;
val /= 3; if (val <= 0) val = 1;
}
#if 0
/* The OfficeJets claim to support >8 bits per color, but it may not
* work on some models. This code (if not commented out) disables it. */
if ((sanei_hp_device_probe (&compat, scsi) == SANE_STATUS_GOOD) &&
(compat & HP_COMPAT_OJ_1150C)) {
if (maxval>8) maxval=8;
}
#endif
}
choices = _make_choice_list(this->descriptor->choices, minval, maxval);
@ -1114,7 +1193,8 @@ _probe_scan_type (_HpOption this, HpScsi scsi, HpOptSet optset,
/* Inquire XPA capability is supported only by IIcx and 6100c/4c/3c. */
/* But more devices support XPA scan window. So dont inquire XPA cap. */
if ( compat & ( HP_COMPAT_2CX | HP_COMPAT_4C | HP_COMPAT_4P
| HP_COMPAT_5P | HP_COMPAT_5100C | HP_COMPAT_6200C) )
| HP_COMPAT_5P | HP_COMPAT_5100C | HP_COMPAT_6200C) &&
!(compat&HP_COMPAT_OJ_1150C) )
{
scan_types[numchoices++] = this->descriptor->choices[2];
}
@ -1222,8 +1302,6 @@ static SANE_Status _probe_front_button(_HpOption this, HpScsi scsi,
HpOptSet optset, HpData data)
{
int val = 0;
const HpDeviceInfo *info =
sanei_hp_device_info_get(sanei_hp_scsi_devicename(scsi));
if ( sanei_hp_scl_inquire(scsi, SCL_FRONT_BUTTON, &val, 0, 0)
!= SANE_STATUS_GOOD )
@ -2412,8 +2490,22 @@ _enable_halftonevec (HpOption this, HpOptSet optset, HpData data,
static hp_bool_t
_enable_data_width (HpOption this, HpOptSet optset, HpData data,
const HpDeviceInfo *info)
{enum hp_scanmode_e mode;
mode = sanei_hp_optset_scanmode (optset, data);
return ( (mode == HP_SCANMODE_GRAYSCALE) || (mode == HP_SCANMODE_COLOR) );
}
static hp_bool_t
_enable_out8 (HpOption this, HpOptSet optset, HpData data,
const HpDeviceInfo *info)
{
return (sanei_hp_optset_scanmode (optset, data) == HP_SCANMODE_COLOR);
if (hp_optset_isEnabled (optset, data, SANE_NAME_BIT_DEPTH, info))
{
int data_width = sanei_hp_optset_data_width (optset, data);
return (((data_width > 8) && (data_width <= 16)) || (data_width > 24));
}
return 0;
}
static hp_bool_t
@ -2507,7 +2599,7 @@ static const struct hp_option_descriptor_s SCAN_MODE_GROUP[1] = {{
static const struct hp_option_descriptor_s PREVIEW_MODE[1] = {{
SCANNER_OPTION(PREVIEW, BOOL, NONE),
NO_REQUIRES,
_probe_preview,
_probe_bool,
0,0,0,0,0,0,0,0,0,0,0,0 /* for gcc-s sake */
}};
@ -2553,6 +2645,14 @@ static const struct hp_option_descriptor_s CONTRAST[1] = {{
_probe_int_brightness, _program_generic_simulate, _enable_brightness,
0, 0, 0, 0, 0, SCL_CONTRAST, -127, 127, 0, 0
}};
#ifdef SCL_SHARPENING
static const struct hp_option_descriptor_s SHARPENING[1] = {{
SCANNER_OPTION(SHARPENING, INT, NONE),
NO_REQUIRES,
_probe_int, _program_generic, 0,
0, 0, 0, 0, 0, SCL_SHARPENING, -127, 127, 0, 0
}};
#endif
static const struct hp_option_descriptor_s AUTO_THRESHOLD[1] = {{
SCANNER_OPTION(AUTO_THRESHOLD, BOOL, NONE),
NO_REQUIRES,
@ -2779,6 +2879,27 @@ static const struct hp_option_descriptor_s BIT_DEPTH[1] = {{
1, 1, 1, 0, 1, SCL_DATA_WIDTH, 0, 0, 0, _data_widths
}};
static const struct hp_option_descriptor_s OUT8[1] =
{
{
SCANNER_OPTION(OUTPUT_8BIT, BOOL, NONE),
NO_REQUIRES, /* enum hp_device_compat_e requires */
_probe_bool, /* SANE_Status (*probe)() */
0, /* SANE_Status (*program)() */
_enable_out8, /* hp_bool_t (*enable)() */
0, /* hp_bool_t has_global_effect */
0, /* hp_bool_t affects_scan_params */
0, /* hp_bool_t program_immediate */
0, /* hp_bool_t suppress_for_scan */
0, /* hp_bool_t may_change */
0, /* HpScl scl_command */
0, /* int minval */
0, /* int maxval */
0, /* int startval */
0 /* HpChoice choices */
}
};
/* The 100% setting may cause problems within the scanner */
static const struct hp_choice_s _ps_exposure_times[] = {
/* {0, "100%", 0, 0, 0}, */
@ -2839,7 +2960,7 @@ static const struct hp_option_descriptor_s CHANGE_DOC[1] = {{
static const struct hp_option_descriptor_s UNLOAD[1] = {{
SCANNER_OPTION(UNLOAD, BUTTON, NONE),
NO_REQUIRES,
_probe_bool, _program_unload, 0,
_probe_unload, _program_unload, 0,
0, 0, 1, 1, 0, SCL_UNLOAD, 0, 0, 0, 0
}};
@ -2983,7 +3104,11 @@ static HpOptionDescriptor hp_options[] = {
SCAN_MODE, SCAN_RESOLUTION, DEVPIX_RESOLUTION,
ENHANCEMENT_GROUP,
BRIGHTNESS, CONTRAST, AUTO_THRESHOLD,
BRIGHTNESS, CONTRAST,
#ifdef SCL_SHARPENING
SHARPENING,
#endif
AUTO_THRESHOLD,
ADVANCED_GROUP,
CUSTOM_GAMMA,
@ -3008,7 +3133,7 @@ static HpOptionDescriptor hp_options[] = {
#endif
HALFTONE_PATTERN_8x8, HORIZONTAL_DITHER_8x8,
SCAN_SPEED, SMOOTHING, MEDIA, PS_EXPOSURE_TIME, BIT_DEPTH,
SCAN_SPEED, SMOOTHING, MEDIA, PS_EXPOSURE_TIME, BIT_DEPTH, OUT8,
SCAN_SOURCE, BUTTON_WAIT, UNLOAD_AFTER_SCAN,
CHANGE_DOC, UNLOAD, CALIBRATE,
@ -3099,6 +3224,25 @@ sanei_hp_optset_scanmode (HpOptSet this, HpData data)
return hp_option_getint(mode, data);
}
hp_bool_t
sanei_hp_optset_output_8bit (HpOptSet this, HpData data)
{
HpOption option_out8;
int out8;
option_out8 = hp_optset_get(this, OUT8);
if (option_out8)
{
out8 = hp_option_getint(option_out8, data);
return out8;
}
return 0;
}
/* Returns the data width that is send to the scanner, depending */
/* on the scanmode. (b/w: 1, gray: 8..12, color: 24..36 */
int
sanei_hp_optset_data_width (HpOptSet this, HpData data)
{
@ -3114,12 +3258,19 @@ sanei_hp_optset_data_width (HpOptSet this, HpData data)
break;
case HP_SCANMODE_GRAYSCALE:
datawidth = 8;
opt_dwidth = hp_optset_get(this, BIT_DEPTH);
if (opt_dwidth)
datawidth = hp_option_getint (opt_dwidth, data);
else
datawidth = 8;
break;
case HP_SCANMODE_COLOR:
opt_dwidth = hp_optset_get(this, BIT_DEPTH);
datawidth = 3 * hp_option_getint (opt_dwidth, data);
if (opt_dwidth)
datawidth = 3 * hp_option_getint (opt_dwidth, data);
else
datawidth = 24;
break;
}
return datawidth;
@ -3148,7 +3299,7 @@ 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)
{
HpOption mode;
int wait, sec_dir;
int wait;
if ((mode = hp_optset_get(this, BUTTON_WAIT)) == 0)
return(0);
@ -3254,6 +3405,20 @@ hp_optset_fix_geometry_options (HpOptSet this, HpDevice dev)
return SANE_STATUS_GOOD;
}
static void
hp_optset_reprogram (HpOptSet this, HpData data, HpScsi scsi)
{
int i;
DBG(5, "hp_optset_reprogram: %lu options\n",
(unsigned long) this->num_opts);
for (i = 0; i < (int)this->num_opts; i++)
hp_option_reprogram(this->options[i], this, data, scsi);
DBG(5, "hp_optset_reprogram: finished\n");
}
static void
hp_optset_reprobe (HpOptSet this, HpData data, HpScsi scsi)
{
@ -3265,6 +3430,7 @@ hp_optset_reprobe (HpOptSet this, HpData data, HpScsi scsi)
for (i = 0; i < (int)this->num_opts; i++)
hp_option_reprobe(this->options[i], this, data, scsi);
DBG(5, "hp_optset_reprobe: finished\n");
}
static void
@ -3344,6 +3510,8 @@ sanei_hp_optset_download (HpOptSet this, HpData data, HpScsi scsi)
is_preview = hp_option_getint (option, data);
if ( is_preview )
{
/* For preview we only use 8 bit per channel */
DBG(3, "sanei_hp_optset_download: Set up preview options\n");
info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) );
@ -3355,6 +3523,10 @@ sanei_hp_optset_download (HpOptSet this, HpData data, HpScsi scsi)
{
sanei_hp_scl_set(scsi, SCL_DATA_WIDTH, 24);
}
else if ((data_width > 8) && (data_width <= 16))
{
sanei_hp_scl_set(scsi, SCL_DATA_WIDTH, 8);
}
}
}
}
@ -3441,6 +3613,8 @@ sanei_hp_optset_control (HpOptSet this, HpData data,
HpOption opt = hp_optset_getByIndex(this, optnum);
SANE_Int my_info = 0;
DBG(3,"sanei_hp_optset_control: %s\n", opt ? opt->descriptor->name : "");
if (infop)
*infop = 0;
else
@ -3458,6 +3632,15 @@ sanei_hp_optset_control (HpOptSet this, HpData data,
if ((*infop & SANE_INFO_RELOAD_OPTIONS) != 0)
{const HpDeviceInfo *info;
DBG(3,"sanei_hp_optset_control: reprobe\n");
/* At first we try to reprogram the parameters that may have changed */
/* by an option that had a global effect. This is necessary to */
/* specify options in an arbitrary order. Example: */
/* Changing scan mode resets scan resolution in the scanner. */
/* If resolution is set from the API before scan mode, we must */
/* reprogram the resolution afterwards. */
hp_optset_reprogram(this, data, scsi);
hp_optset_reprobe(this, data, scsi);
info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) );
hp_optset_updateEnables(this, data, info);
@ -3492,16 +3675,28 @@ sanei_hp_optset_guessParameters (HpOptSet this, HpData data,
p->format = SANE_FRAME_GRAY;
p->depth = 8;
p->bytes_per_line = p->pixels_per_line;
if ( !sanei_hp_optset_output_8bit (this, data) )
{
data_width = sanei_hp_optset_data_width (this, data);
if ( data_width > 8 )
{
p->depth *= 2;
p->bytes_per_line *= 2;
}
}
break;
case HP_SCANMODE_COLOR: /* RGB */
p->format = SANE_FRAME_RGB;
p->depth = 8;
p->bytes_per_line = 3 * p->pixels_per_line;
data_width = sanei_hp_optset_data_width (this, data);
if ( data_width > 24 )
if ( !sanei_hp_optset_output_8bit (this, data) )
{
p->depth *= 2;
p->bytes_per_line *= 2;
data_width = sanei_hp_optset_data_width (this, data);
if ( data_width > 24 )
{
p->depth *= 2;
p->bytes_per_line *= 2;
}
}
break;
default:

Wyświetl plik

@ -51,6 +51,13 @@
*
* FIXME: this should become standard
*/
#ifndef SANE_NAME_SHARPENING
# define SANE_NAME_SHARPENING "sharpening"
# define SANE_TITLE_SHARPENING "Sharpening"
# define SANE_DESC_SHARPENING "Set sharpening value."
#endif
#ifndef SANE_NAME_AUTO_THRESHOLD
# define SANE_NAME_AUTO_THRESHOLD "auto-threshold"
# define SANE_TITLE_AUTO_THRESHOLD "Auto Threshold"
@ -140,6 +147,13 @@
# define SANE_DESC_UPDATE "Update options."
#endif
#ifndef SANE_NAME_OUTPUT_8BIT
# define SANE_NAME_OUTPUT_8BIT "output-8bit"
# define SANE_TITLE_OUTPUT_8BIT "8 bit output"
# define SANE_DESC_OUTPUT_8BIT "Use bit depth greater eight internally,\
but output only eight bits"
#endif
#ifndef SANE_NAME_BUTTON_WAIT
# define SANE_NAME_BUTTON_WAIT "button-wait"
# define SANE_TITLE_BUTTON_WAIT "Front button wait"
@ -248,6 +262,7 @@ SANE_Status sanei_hp_optset_control (HpOptSet this, HpData data,
SANE_Status sanei_hp_optset_guessParameters (HpOptSet this, HpData data,
SANE_Parameters * p);
enum hp_scanmode_e sanei_hp_optset_scanmode (HpOptSet this, HpData data);
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);

Wyświetl plik

@ -69,6 +69,10 @@ extern int sanei_debug_hp;
#include "hp-scsi.h"
#include "hp-scl.h"
#ifdef HAVE_PTAL
#include <ptal.h>
#endif
#define HP_SCSI_INQ_LEN (36)
#define HP_SCSI_CMD_LEN (6)
#define HP_SCSI_BUFSIZ (HP_SCSI_MAX_WRITE + HP_SCSI_CMD_LEN)
@ -80,6 +84,10 @@ extern int sanei_debug_hp;
*/
struct hp_scsi_s
{
#ifdef HAVE_PTAL
ptalDevice_t dev;
ptalChannel_t chan;
#endif
int fd;
char * devname;
@ -119,6 +127,10 @@ static SANE_Status
hp_nonscsi_write (HpScsi this, hp_byte_t *data, size_t len, HpConnect connect)
{int n = -1;
#ifdef HAVE_PTAL
int isReset;
struct timeval startTimeout,continueTimeout;
#endif
if (len <= 0) return SANE_STATUS_GOOD;
@ -140,6 +152,45 @@ hp_nonscsi_write (HpScsi this, hp_byte_t *data, size_t len, HpConnect connect)
n = -1;
break;
case HP_CONNECT_PTAL:
#ifndef HAVE_PTAL
n = -1;
#else
/* Check to see if we need to re-open the scan channel in case
* JetDirect closed it due to an idle timeout. */
if (ptalChannelOpenOrReopen(this->chan)==PTAL_ERROR) {
break;
}
if (ptalChannelPrepareForSelect(this->chan,&this->fd,0,0,0,0)==
PTAL_ERROR) {
break;
}
/* If we're sending an SCL RESET command, then flush stale
* response data after sending the command. Otherwise,
* flush stale data before sending the command. This is
* necessary because data is buffered between us and the
* scanner, which will not be affected by the SCL RESET. */
isReset=(len==2 && data[0]==27 && data[1]=='E');
startTimeout.tv_sec=0;
startTimeout.tv_usec=0;
continueTimeout.tv_sec=2;
continueTimeout.tv_usec=0;
if (!isReset) {
ptalChannelFlush(this->chan,&startTimeout,&continueTimeout);
}
n=ptalChannelWrite(this->chan,data,len);
if (isReset) {
ptalChannelFlush(this->chan,&startTimeout,&continueTimeout);
}
#endif
break;
default:
n = -1;
break;
@ -152,9 +203,13 @@ hp_nonscsi_write (HpScsi this, hp_byte_t *data, size_t len, HpConnect connect)
}
static SANE_Status
hp_nonscsi_read (HpScsi this, hp_byte_t *data, size_t *len, HpConnect connect)
hp_nonscsi_read (HpScsi this, hp_byte_t *data, size_t *len, HpConnect connect,
int isResponse)
{int n = -1;
#ifdef HAVE_PTAL
struct timeval continueTimeout;
#endif
if (*len <= 0) return SANE_STATUS_GOOD;
@ -176,6 +231,18 @@ hp_nonscsi_read (HpScsi this, hp_byte_t *data, size_t *len, HpConnect connect)
n = -1;
break;
case HP_CONNECT_PTAL:
#ifndef HAVE_PTAL
n = -1;
#else
continueTimeout.tv_sec=0;
if (isResponse) continueTimeout.tv_sec=1;
if (*len>1024) continueTimeout.tv_sec=2;
continueTimeout.tv_usec=10000;
n=ptalSclChannelRead(this->chan,data,*len,0,&continueTimeout,isResponse);
#endif
break;
default:
n = -1;
break;
@ -237,6 +304,12 @@ hp_nonscsi_open (const char *devname, int *fd, HpConnect connect)
status = SANE_STATUS_INVAL;
break;
case HP_CONNECT_PTAL:
/* This is handled in hp_nonscsi_write()
* because we need more than the file descriptor. */
status = SANE_STATUS_INVAL;
break;
default:
status = SANE_STATUS_INVAL;
break;
@ -271,6 +344,11 @@ hp_nonscsi_close (int fd, HpConnect connect)
case HP_CONNECT_RESERVE:
break;
case HP_CONNECT_PTAL:
/* This is handled in hp_scsi_close()
* because we need more than the file descriptor. */
break;
default:
break;
}
@ -286,6 +364,26 @@ sanei_hp_nonscsi_new (HpScsi * newp, const char * devname, HpConnect connect)
if (!new)
return SANE_STATUS_NO_MEM;
#ifdef HAVE_PTAL
if (connect==HP_CONNECT_PTAL) {
/* The constant allocation and deallocation of the HpScsi object
* does not work well with OfficeJets, especially when connected
* to JetDirect. As a somewhat inefficient workaround, we
* allocate and set up the PTAL channel once, and look it up by
* device name and service type on successive HpScsi instantiations. */
new->dev=ptalDeviceOpen((char *)devname);
if (!new->dev) {
sanei_hp_free(new);
return SANE_STATUS_NO_MEM;
}
new->chan=ptalChannelFindOrAllocate(new->dev,PTAL_STYPE_SCAN,0,0);
if (!new->chan) {
sanei_hp_free(new);
return SANE_STATUS_NO_MEM;
}
new->fd=PTAL_NO_FD;
} else {
#endif
status = hp_nonscsi_open(devname, &new->fd, connect);
if (FAILED(status))
{
@ -293,6 +391,9 @@ sanei_hp_nonscsi_new (HpScsi * newp, const char * devname, HpConnect connect)
sanei_hp_free(new);
return SANE_STATUS_IO_ERROR;
}
#ifdef HAVE_PTAL
}
#endif
/* For SCSI-devices we would have the inquire command here */
strncpy (new->inq_data, "\003zzzzzzzHP MODELx R000",
@ -308,15 +409,28 @@ sanei_hp_nonscsi_new (HpScsi * newp, const char * devname, HpConnect connect)
static void
hp_scsi_close (HpScsi this)
{HpConnect connect;
DBG(3, "scsi_close: closing fd %ld\n", (long)this->fd);
connect = sanei_hp_scsi_get_connect (this);
#ifdef HAVE_PTAL
if (connect==HP_CONNECT_PTAL) {
ptalChannelClose(this->chan);
} else {
#endif
assert(this->fd >= 0);
if (connect != HP_CONNECT_SCSI)
hp_nonscsi_close (this->fd, connect);
else
sanei_scsi_close (this->fd);
#ifdef HAVE_PTAL
}
#endif
}
SANE_Status
@ -374,12 +488,29 @@ sanei_hp_scsi_new (HpScsi * newp, const char * devname)
return SANE_STATUS_GOOD;
}
void
sanei_hp_scsi_destroy (HpScsi this)
{
assert(this->fd >= 0);
DBG(3, "scsi_close: closing fd %d\n", this->fd);
/* The "completely" parameter was added for OfficeJet support.
* For JetDirect connections, closing and re-opening the scan
* channel is very time consuming. Also, the OfficeJet G85
* unloads a loaded document in the ADF when the scan channel
* gets closed. The solution is to "completely" destroy the
* connection, including closing and deallocating the PTAL
* channel, when initially probing the device in hp-device.c,
* but leave it open while the frontend is actually using the
* device (from hp-handle.c), and "completely" destroy it when
* the frontend closes its handle. */
void
sanei_hp_scsi_destroy (HpScsi this,int completely)
{
/* Moved to hp_scsi_close():
* assert(this->fd >= 0);
* DBG(3, "scsi_close: closing fd %d\n", this->fd);
*/
#ifdef HAVE_PTAL
if (sanei_hp_scsi_get_connect(this)!=HP_CONNECT_PTAL || completely)
#endif
hp_scsi_close (this);
if ( this->devname ) sanei_hp_free (this->devname);
sanei_hp_free(this);
@ -542,8 +673,13 @@ hp_scsi_scl(HpScsi this, HpScl scl, int val)
}
/* The OfficeJets tend to return inquiry responses containing array
* data in two packets. The added "isResponse" parameter tells
* ptalSclChannelRead whether it should keep reading until it gets
* a well-formed response. Naturally, this parameter would be zero
* when reading scan data. */
static SANE_Status
hp_scsi_read (HpScsi this, void * dest, size_t *len)
hp_scsi_read (HpScsi this, void * dest, size_t *len, int isResponse)
{
HpConnect connect;
static hp_byte_t read_cmd[6] = { 0x08, 0, 0, 0, 0, 0 };
@ -562,7 +698,7 @@ hp_scsi_read (HpScsi this, void * dest, size_t *len)
}
else
{
RETURN_IF_FAIL( hp_nonscsi_read (this, dest, len, connect) );
RETURN_IF_FAIL( hp_nonscsi_read (this, dest, len, connect, isResponse) );
}
DBG(16, "scsi_read: %lu bytes:\n", (unsigned long) *len);
DBGDUMP(16, dest, *len);
@ -575,6 +711,7 @@ static int signal_caught = 0;
static RETSIGTYPE
signal_catcher (int sig)
{
DBG(1,"signal_catcher(sig=%d): old signal_caught=%d\n",sig,signal_caught);
if (!signal_caught)
signal_caught = sig;
}
@ -688,6 +825,53 @@ hp_scale_to_16bit(int count, register unsigned char *data, int depth,
}
}
static void
hp_scale_to_8bit(int count, register unsigned char *data, int depth,
hp_bool_t invert)
{
register unsigned int tmp, mask;
register hp_bool_t lowbyte_first = is_lowbyte_first_byteorder ();
unsigned int shift1 = depth-8;
int k;
unsigned char *dataout = data;
if ((count <= 0) || (shift1 <= 0)) return;
mask = 1;
for (k = 1; k < depth; k++) mask |= (1 << k);
if (lowbyte_first)
{
while (count--) {
tmp = ((((unsigned int)data[0])<<8) | ((unsigned int)data[1])) & mask;
tmp >>= shift1;
if (invert) tmp = ~tmp;
*(dataout++) = tmp & 255U;
data += 2;
}
}
else /* Highbyte first */
{
while (count--) {
tmp = ((((unsigned int)data[0])<<8) | ((unsigned int)data[1])) & mask;
tmp >>= shift1;
if (invert) tmp = ~tmp;
*(dataout++) = tmp & 255U;
data += 2;
}
}
}
static void
hp_soft_invert(int count, register unsigned char *data) {
while (count>0) {
*data = ~(*data);
data++;
count--;
}
}
static PROCDATA_HANDLE *
process_data_init (HpProcessData *procdata, const unsigned char *map,
int outfd, hp_bool_t use_imgbuf)
@ -717,6 +901,7 @@ process_data_init (HpProcessData *procdata, const unsigned char *map,
if ( procdata->mirror_vertical || use_imgbuf)
{
tsz = procdata->lines*procdata->bytes_per_line;
if (procdata->out8) tsz /= 2;
ph->image_ptr = ph->image_buf = sanei_hp_alloc (tsz);
if ( !ph->image_buf )
{
@ -756,7 +941,9 @@ process_data_write (PROCDATA_HANDLE *ph, unsigned char *data, int nbytes)
return SANE_STATUS_GOOD;
DBG(12, "process_data_write: write %d bytes\n", ph->wr_buf_size);
if ( write (ph->outfd, ph->wr_buf, ph->wr_buf_size) != ph->wr_buf_size)
/* Don't write data if we got a signal in the meantime */
if ( signal_caught
|| (write (ph->outfd, ph->wr_buf, ph->wr_buf_size) != ph->wr_buf_size))
{
DBG(1, "process_data_write: write failed: %s\n",
signal_caught ? "signal caught" : strerror(errno));
@ -768,7 +955,8 @@ process_data_write (PROCDATA_HANDLE *ph, unsigned char *data, int nbytes)
/* For large amount of data write it from data-buffer */
while ( nbytes > ph->wr_buf_size )
{
if ( write (ph->outfd, data, ph->wr_buf_size) != ph->wr_buf_size)
if ( signal_caught
|| (write (ph->outfd, data, ph->wr_buf_size) != ph->wr_buf_size))
{
DBG(1, "process_data_write: write failed: %s\n",
signal_caught ? "signal caught" : strerror(errno));
@ -787,12 +975,11 @@ process_data_write (PROCDATA_HANDLE *ph, unsigned char *data, int nbytes)
return SANE_STATUS_GOOD;
}
static SANE_Status
process_scanline (PROCDATA_HANDLE *ph, unsigned char *linebuf,
int bytes_per_line)
{
{int out_bytes_per_line = bytes_per_line;
HpProcessData *procdata;
if (ph == NULL) return SANE_STATUS_INVAL;
@ -802,18 +989,33 @@ process_scanline (PROCDATA_HANDLE *ph, unsigned char *linebuf,
hp_data_map (ph->map, bytes_per_line, linebuf);
if (procdata->bits_per_channel > 8)
hp_scale_to_16bit( bytes_per_line/2, linebuf,
procdata->bits_per_channel,
procdata->invert);
{
if (procdata->out8)
{
hp_scale_to_8bit( bytes_per_line/2, linebuf,
procdata->bits_per_channel,
procdata->invert);
out_bytes_per_line /= 2;
}
else
{
hp_scale_to_16bit( bytes_per_line/2, linebuf,
procdata->bits_per_channel,
procdata->invert);
}
} else if (procdata->invert) {
hp_soft_invert(bytes_per_line,linebuf);
}
if ( ph->image_buf )
{
DBG(5, "process_scanline: save in memory\n");
if ( ph->image_ptr+bytes_per_line-1 <= ph->image_buf+ph->image_buf_size-1 )
if ( ph->image_ptr+out_bytes_per_line-1
<= ph->image_buf+ph->image_buf_size-1 )
{
memcpy(ph->image_ptr, linebuf, bytes_per_line);
ph->image_ptr += bytes_per_line;
memcpy(ph->image_ptr, linebuf, out_bytes_per_line);
ph->image_ptr += out_bytes_per_line;
}
else
{
@ -823,7 +1025,7 @@ process_scanline (PROCDATA_HANDLE *ph, unsigned char *linebuf,
else /* Save scanlines in a bigger buffer. */
{ /* Otherwise we will get performance problems */
RETURN_IF_FAIL ( process_data_write (ph, linebuf, bytes_per_line) );
RETURN_IF_FAIL ( process_data_write (ph, linebuf, out_bytes_per_line) );
}
return SANE_STATUS_GOOD;
}
@ -892,7 +1094,7 @@ process_data_flush (PROCDATA_HANDLE *ph)
if ( ph->wr_left != ph->wr_buf_size ) /* Something in write buffer ? */
{
nbytes = ph->wr_buf_size - ph->wr_left;
if ( write (ph->outfd, ph->wr_buf, nbytes) != nbytes)
if ( signal_caught || (write (ph->outfd, ph->wr_buf, nbytes) != nbytes))
{
DBG(1, "process_data_flush: write failed: %s\n",
signal_caught ? "signal caught" : strerror(errno));
@ -906,6 +1108,7 @@ process_data_flush (PROCDATA_HANDLE *ph)
if ( ph->image_buf )
{
bytes_per_line = procdata->bytes_per_line;
if (procdata->out8) bytes_per_line /= 2;
image_len = (size_t) (ph->image_ptr - ph->image_buf);
num_lines = ((int)(image_len + bytes_per_line-1)) / bytes_per_line;
@ -917,7 +1120,8 @@ process_data_flush (PROCDATA_HANDLE *ph)
image_data = ph->image_buf + (num_lines-1) * bytes_per_line;
while (num_lines > 0 )
{
if (write(ph->outfd, image_data, bytes_per_line) != bytes_per_line)
if ( signal_caught
|| (write(ph->outfd, image_data, bytes_per_line) != bytes_per_line))
{
DBG(1,"process_data_finish: write from memory failed: %s\n",
signal_caught ? "signal caught" : strerror(errno));
@ -933,7 +1137,8 @@ process_data_flush (PROCDATA_HANDLE *ph)
image_data = ph->image_buf;
while (num_lines > 0 )
{
if (write(ph->outfd, image_data, bytes_per_line) != bytes_per_line)
if ( signal_caught
|| (write(ph->outfd, image_data, bytes_per_line) != bytes_per_line))
{
DBG(1,"process_data_finish: write from memory failed: %s\n",
signal_caught ? "signal caught" : strerror(errno));
@ -1173,7 +1378,7 @@ sanei_hp_scsi_pipeout (HpScsi this, int outfd, HpProcessData *procdata)
DBG(3, "do_read: try to read data (%lu bytes)\n", (unsigned long)nread);
status = hp_scsi_read (this, read_buf, &nread);
status = hp_scsi_read (this, read_buf, &nread, 0);
if (status != SANE_STATUS_GOOD)
{
DBG(1, "do_read: Error from scsi_read: %s\n",sane_strstatus(status));
@ -1258,7 +1463,7 @@ _hp_scl_inq (HpScsi scsi, HpScl scl, HpScl inq_cmnd,
RETURN_IF_FAIL( hp_scsi_scl(scsi, inq_cmnd, SCL_INQ_ID(scl)) );
status = hp_scsi_read(scsi, buf, &bufsize);
status = hp_scsi_read(scsi, buf, &bufsize, 1);
if (FAILED(status))
{
DBG(1, "scl_inq: read failed (%s)\n", sane_strstatus(status));
@ -1341,7 +1546,7 @@ sanei_hp_scl_upload_binary (HpScsi scsi, HpScl scl, size_t *lengthhp,
RETURN_IF_FAIL( hp_scsi_scl(scsi, SCL_UPLOAD_BINARY_DATA, SCL_INQ_ID(scl)) );
status = hp_scsi_read(scsi, buf, &bufsize);
status = hp_scsi_read(scsi, buf, &bufsize, 0);
if (FAILED(status))
{
DBG(1, "scl_upload_binary: read failed (%s)\n", sane_strstatus(status));
@ -1397,7 +1602,7 @@ sanei_hp_scl_upload_binary (HpScsi scsi, HpScl scl, size_t *lengthhp,
if ( val > 0 )
{
sv = val;
status = hp_scsi_read(scsi, hpdata, &sv);
status = hp_scsi_read(scsi, hpdata, &sv, 0);
if (status != SANE_STATUS_GOOD)
sanei_hp_free ( *bufhp );
}

Wyświetl plik

@ -72,6 +72,7 @@
#define SCL_CONTRAST HP_SCL_CONTROL(10316, 'a', 'K')
#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_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')
@ -116,6 +117,8 @@
#define SCL_HP_MODEL_8 HP_SCL_PARAMETER(15)
#define SCL_HP_MODEL_9 HP_SCL_PARAMETER(16)
#define SCL_HP_MODEL_10 HP_SCL_PARAMETER(17)
#define SCL_HP_MODEL_11 HP_SCL_PARAMETER(18)
#define SCL_HP_MODEL_12 HP_SCL_PARAMETER(19)
#define SCL_HP_MODEL_14 HP_SCL_PARAMETER(21)
#define SCL_HP_MODEL_16 HP_SCL_PARAMETER(31)
#define SCL_HP_MODEL_17 HP_SCL_PARAMETER(32)

Wyświetl plik

@ -49,7 +49,7 @@
SANE_Status sanei_hp_nonscsi_new (HpScsi * newp, const char * devname,
HpConnect connect);
SANE_Status sanei_hp_scsi_new (HpScsi * newp, const char * devname);
void sanei_hp_scsi_destroy (HpScsi this);
void sanei_hp_scsi_destroy (HpScsi this,int completely);
hp_byte_t * sanei_hp_scsi_inq (HpScsi this);
const char *sanei_hp_scsi_model (HpScsi this);

Wyświetl plik

@ -43,9 +43,26 @@
HP Scanner Control Language (SCL).
*/
static char *hp_backend_version = "0.88";
static char *hp_backend_version = "0.91";
/* Changes:
V 0.91, 04-Sep-2000, David Paschal (paschal@rcsis.com):
- Added support for flatbed HP OfficeJets
- (PK) fix problem with cancel preview
V 0.90, 02-Sep-2000, PK:
- fix timing problem between killing child and writing to pipe
- change fprintf(stderr,...) to DBG
- change include <sane..> to "sane.." in hp.h
- change handling of options that have global effects.
i.e. if option scanmode is received (has global effect),
all options that "may change" are send to the scanner again.
This fixes a problem that --resolution specified infront of
--mode on command line of scanimage was ignored.
NOTE: This change does not allow to specify --depth 12 infront of
--mode color, because --depth is only enabled with --mode color.
- add depth greater 8 bits for mode grayscale
- add option for 8 bit output but 10/12 bit scanning
V 0.88, 25-Jul-2000, PK:
- remove inlines
V 0.88, 20-Jul-2000, PK:
@ -162,6 +179,10 @@ static char *hp_backend_version = "0.88";
#include "hp-device.h"
#include "hp-handle.h"
#ifdef HAVE_PTAL
#include <ptal.h>
#endif
#ifndef PATH_MAX
# define PATH_MAX 1024
#endif
@ -174,19 +195,25 @@ sanei_hp_dbgdump (const void * bufp, size_t len)
const hp_byte_t *buf = bufp;
int offset = 0;
int i;
FILE * fp = stderr;
char line[128], pt[32];
for (offset = 0; offset < (int)len; offset += 16)
{
fprintf(fp, " 0x%04X ", offset);
sprintf (line," 0x%04X ", offset);
for (i = offset; i < offset + 16 && i < (int)len; i++)
fprintf(fp, " %02X", buf[i]);
{
sprintf (pt," %02X", buf[i]);
strcat (line, pt);
}
while (i++ < offset + 16)
fputs(" ", fp);
fputs(" ", fp);
strcat (line, " ");
strcat (line, " ");
for (i = offset; i < offset + 16 && i < (int)len; i++)
fprintf(fp, "%c", isprint(buf[i]) ? buf[i] : '.');
fputs("\n", fp);
{
sprintf (pt, "%c", isprint(buf[i]) ? buf[i] : '.');
strcat (line, pt);
}
DBG(16,"%s\n",line);
}
}
@ -480,6 +507,7 @@ hp_get_dev (const char *devname, HpDevice* devp)
else if (hp_connect == HP_CONNECT_PIO) connect = "pio";
else if (hp_connect == HP_CONNECT_USB) connect = "usb";
else if (hp_connect == HP_CONNECT_RESERVE) connect = "reserve";
else if (hp_connect == HP_CONNECT_PTAL) connect = "ptal";
else connect = "unknown";
DBG(3, "hp_get_dev: New device %s, connect-%s, scsi-request=%lu\n",
@ -581,6 +609,16 @@ hp_read_config (void)
config->connect = HP_CONNECT_RESERVE;
config->use_scsi_request = 0;
}
else if (strcmp (arg2, "connect-ptal") == 0)
{
#ifdef HAVE_PTAL
config->connect = HP_CONNECT_PTAL;
config->use_scsi_request = 0;
#else
DBG(1,"hp_read_config: connect-ptal:\n");
DBG(1," hp-backend not compiled with PTAL support.\n");
#endif
}
else if (strcmp (arg2, "disable-scsi-request") == 0)
{
config->use_scsi_request = 0;
@ -673,32 +711,42 @@ hp_update_devlist (void)
SANE_Status
sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize)
{
{SANE_Status status;
DBG_INIT();
DBG(3, "init called\n");
DBG(3, "sane_init called\n");
#ifdef HAVE_PTAL
ptalInit();
#endif
hp_destroy();
if (version_code)
*version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, VERSIO);
return hp_init();
status = hp_init();
DBG(3, "sane_init will finish with %s\n", sane_strstatus (status));
return status;
}
void
sane_exit (void)
{
DBG(3, "exit called\n");
DBG(3, "sane_exit called\n");
hp_destroy();
DBG(3, "sane_exit will finish\n");
}
SANE_Status
sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only)
{
DBG(3, "get_devices called\n");
DBG(3, "sane_get_devices called\n");
RETURN_IF_FAIL( hp_update_devlist() );
*device_list = global.devlist;
DBG(3, "sane_get_devices will finish with %s\n",
sane_strstatus (SANE_STATUS_GOOD));
return SANE_STATUS_GOOD;
}
@ -708,6 +756,8 @@ sane_open (SANE_String_Const devicename, SANE_Handle *handle)
HpDevice dev = 0;
HpHandle h;
DBG(3, "sane_open called\n");
RETURN_IF_FAIL( hp_read_config() );
if (devicename[0])
@ -727,6 +777,7 @@ sane_open (SANE_String_Const devicename, SANE_Handle *handle)
RETURN_IF_FAIL( hp_handle_list_add(&global.handle_list, h) );
*handle = h;
DBG(3, "sane_open will finish with %s\n", sane_strstatus (SANE_STATUS_GOOD));
return SANE_STATUS_GOOD;
}
@ -735,15 +786,27 @@ sane_close (SANE_Handle handle)
{
HpHandle h = handle;
DBG(3, "sane_close called\n");
if (!FAILED( hp_handle_list_remove(&global.handle_list, h) ))
sanei_hp_handle_destroy(h);
DBG(3, "sane_close will finish\n");
}
const SANE_Option_Descriptor *
sane_get_option_descriptor (SANE_Handle handle, SANE_Int optnum)
{
HpHandle h = handle;
return sanei_hp_handle_saneoption(h, optnum);
const SANE_Option_Descriptor *optd;
DBG(10, "sane_get_option_descriptor called\n");
optd = sanei_hp_handle_saneoption(h, optnum);
DBG(10, "sane_get_option_descriptor will finish\n");
return optd;
}
SANE_Status
@ -751,21 +814,44 @@ sane_control_option (SANE_Handle handle, SANE_Int optnum,
SANE_Action action, void *valp, SANE_Int *info)
{
HpHandle h = handle;
return sanei_hp_handle_control(h, optnum, action, valp, info);
SANE_Status status;
DBG(10, "sane_control_option called\n");
status = sanei_hp_handle_control(h, optnum, action, valp, info);
DBG(10, "sane_control_option will finish with %s\n",
sane_strstatus (status));
return status;
}
SANE_Status
sane_get_parameters (SANE_Handle handle, SANE_Parameters *params)
{
HpHandle h = handle;
return sanei_hp_handle_getParameters(h, params);
SANE_Status status;
DBG(10, "sane_get_parameters called\n");
status = sanei_hp_handle_getParameters(h, params);
DBG(10, "sane_get_parameters will finish with %s\n",
sane_strstatus (status));
return status;
}
SANE_Status
sane_start (SANE_Handle handle)
{
HpHandle h = handle;
return sanei_hp_handle_startScan(h);
SANE_Status status;
DBG(3, "sane_start called\n");
status = sanei_hp_handle_startScan(h);
DBG(3, "sane_start will finish with %s\n", sane_strstatus (status));
return status;
}
SANE_Status
@ -775,8 +861,12 @@ sane_read (SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len)
size_t length = max_len;
SANE_Status status;
DBG(16, "sane_read called\n");
status = sanei_hp_handle_read(h, buf, &length);
*len = length;
DBG(16, "sane_read will finish with %s\n", sane_strstatus (status));
return status;
}
@ -784,19 +874,40 @@ void
sane_cancel (SANE_Handle handle)
{
HpHandle h = handle;
DBG(3, "sane_cancel called\n");
sanei_hp_handle_cancel(h);
DBG(3, "sane_cancel will finish\n");
}
SANE_Status
sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
{
HpHandle h = handle;
return sanei_hp_handle_setNonblocking(h, non_blocking);
SANE_Status status;
DBG(3, "sane_set_io_mode called\n");
status = sanei_hp_handle_setNonblocking(h, non_blocking);
DBG(3, "sane_set_io_mode will finish with %s\n",
sane_strstatus (status));
return status;
}
SANE_Status
sane_get_select_fd (SANE_Handle handle, SANE_Int *fd)
{
HpHandle h = handle;
return sanei_hp_handle_getPipefd(h, fd);
SANE_Status status;
DBG(10, "sane_get_select_fd called\n");
status = sanei_hp_handle_getPipefd(h, fd);
DBG(10, "sane_get_select_fd will finish with %s\n",
sane_strstatus (status));
return status;
}

Wyświetl plik

@ -46,11 +46,11 @@
#define HP_H_INCLUDED
#include <limits.h>
#include <sys/types.h>
#include <sane/sane.h>
#include "sane/sane.h"
#undef BACKEND_NAME
#define BACKEND_NAME hp
#include <sane/sanei_debug.h>
#include "sane/sanei_debug.h"
/* FIXME: these should be options? */
#undef ENABLE_7x12_TONEMAPS
@ -102,7 +102,8 @@ typedef int hp_bool_t;
typedef unsigned char hp_byte_t;
typedef enum { HP_CONNECT_SCSI, HP_CONNECT_DEVICE,
HP_CONNECT_PIO, HP_CONNECT_USB, HP_CONNECT_RESERVE } HpConnect;
HP_CONNECT_PIO, HP_CONNECT_USB, HP_CONNECT_RESERVE,
HP_CONNECT_PTAL } HpConnect;
typedef struct
{
@ -156,8 +157,10 @@ typedef long int HpScl;
typedef struct
{
int lines;
int bytes_per_line;
int bytes_per_line; /* as received from scanner */
int bits_per_channel;
hp_bool_t out8; /* This flag is set and only set, when data with */
/* depths > 8 is to be mapped to 8 bit output. */
hp_bool_t mirror_vertical;
hp_bool_t invert;
HpScl startscan;