update snapscan to snapshot 20011008

DEVEL_2_0_BRANCH-1
Oliver Schwartz 2001-10-09 09:45:21 +00:00
rodzic e4db2d172b
commit 010db1ed52
9 zmienionych plików z 1784 dodań i 1543 usunięć

Plik diff jest za duży Load Diff

Wyświetl plik

@ -1,47 +1,48 @@
/* sane - Scanner Access Now Easy.
Copyright (C) 1997, 1998 Franck Schnefra, Michel Roelofs,
Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller,
Petter Reinholdtsen, Gary Plewa, Sebastien Sable and Kevin Charter
Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Oliver Schwartz
and Kevin Charter
This file is part of the SANE package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
As a special exception, the authors of SANE give permission for
additional uses of the libraries contained in this release of SANE.
The exception is that, if you link a SANE library with other files
to produce an executable, this does not by itself cause the
resulting executable to be covered by the GNU General Public
License. Your use of that executable is in no way restricted on
account of linking the SANE library code into it.
This exception does not, however, invalidate any other reasons why
the executable file might be covered by the GNU General Public
License.
If you submit changes to SANE to the maintainers to be included in
a subsequent release, you agree by submitting the changes that
those changes may be distributed with this exception intact.
If you write modifications of your own for SANE, it is your choice
whether to permit this exception to apply to your modifications.
If you do not wish that, delete this exception notice.
This file is a component of the implementation of a backend for many
of the the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */
@ -92,15 +93,13 @@ typedef enum
BUF_SRC
} BaseSourceType;
#define SCSISOURCE_BAD_TIME -1
typedef struct
{
SOURCE_GUTS;
SANE_Int scsi_buf_pos; /* current position in scsi buffer */
SANE_Int scsi_buf_max; /* data limit */
SANE_Int absolute_max; /* largest possible data read */
struct timeval time; /* time of last scsi read (usec) */
SANE_Int scsi_buf_pos; /* current position in scsi buffer */
SANE_Int scsi_buf_max; /* data limit */
SANE_Int absolute_max; /* largest possible data read */
} SCSISource;
static SANE_Int SCSISource_remaining (Source *pself)
@ -111,69 +110,24 @@ static SANE_Int SCSISource_remaining (Source *pself)
static SANE_Status SCSISource_get (Source *pself,
SANE_Byte *pbuf,
SANE_Int *plen)
SANE_Int *plen)
{
SCSISource *ps = (SCSISource *) pself;
SANE_Status status = SANE_STATUS_GOOD;
SANE_Int remaining = *plen;
static SANE_Int warned_expected_bytes = 0;
char* me = "SCSISource_get";
DBG (DL_CALL_TRACE, "%s\n", me);
while (remaining > 0
&&
pself->remaining(pself) > 0
&&
status == SANE_STATUS_GOOD)
&& pself->remaining(pself) > 0
&& status == SANE_STATUS_GOOD)
{
SANE_Int ndata = ps->scsi_buf_max - ps->scsi_buf_pos;
DBG (DL_DATA_TRACE, "%s: ndata %d; remaining %d\n", me, ndata, remaining);
if (ndata == 0)
{
/* read more data */
struct timeval oldtime = ps->time;
if (ps->time.tv_sec != SCSISOURCE_BAD_TIME
&&
gettimeofday(&(ps->time), NULL) == 0)
{
/* estimate number of lines to read from the elapsed time
since the last read and the scanner's reported speed */
double msecs = (ps->time.tv_sec - oldtime.tv_sec)*1000.0
+ (ps->time.tv_usec - oldtime.tv_usec)/1000.0;
ps->pss->expected_read_bytes =
((int) (msecs/ps->pss->ms_per_line))*ps->pss->bytes_per_line;
if(ps->pss->pdev->model == ACER300F
||
ps->pss->pdev->model == SNAPSCAN310
||
ps->pss->pdev->model == PRISA620S
||
ps->pss->pdev->model == SNAPSCAN1212U
||
ps->pss->pdev->model == SNAPSCAN1236S
||
ps->pss->pdev->model == SNAPSCANE50
||
ps->pss->pdev->model == VUEGO310S
||
ps->pss->pdev->model == VUEGO610S)
{
ps->pss->expected_read_bytes = (size_t) ps->absolute_max;
}
if (ps->pss->expected_read_bytes == 0)
{
if (!warned_expected_bytes)
{
warned_expected_bytes++;
DBG (DL_MAJOR_ERROR,
"%s: Hung up because expected bytes is 0. Please report!",
__FUNCTION__);
}
}
}
else
{
/* use the "lines_per_read" values */
ps->pss->expected_read_bytes = ps->absolute_max;
/*
SANE_Int lines;
if (is_colour_mode(actual_mode(ps->pss)) == SANE_TRUE)
@ -181,11 +135,9 @@ static SANE_Status SCSISource_get (Source *pself,
else
lines = ps->pss->gs_lpr;
ps->pss->expected_read_bytes = lines * ps->pss->bytes_per_line;
}
*/
ps->pss->expected_read_bytes = MIN(ps->pss->expected_read_bytes,
ps->pss->bytes_remaining);
ps->pss->expected_read_bytes = MIN(ps->pss->expected_read_bytes,
(size_t) ps->absolute_max);
ps->pss->bytes_remaining);
ps->scsi_buf_pos = 0;
ps->scsi_buf_max = 0;
status = scsi_read (ps->pss, READ_IMAGE);
@ -194,6 +146,9 @@ static SANE_Status SCSISource_get (Source *pself,
ps->scsi_buf_max = ps->pss->read_bytes;
ndata = ps->pss->read_bytes;
ps->pss->bytes_remaining -= ps->pss->read_bytes;
DBG (DL_DATA_TRACE, "%s: pos: %d; max: %d; expected: %d; read: %d\n",
me, ps->scsi_buf_pos, ps->scsi_buf_max, ps->pss->expected_read_bytes,
ps->pss->read_bytes);
}
ndata = MIN(ndata, remaining);
memcpy (pbuf, ps->pss->buf + ps->scsi_buf_pos, (size_t)ndata);
@ -207,6 +162,7 @@ static SANE_Status SCSISource_get (Source *pself,
static SANE_Status SCSISource_done (Source *pself)
{
DBG(DL_MINOR_INFO, "SCSISource_done\n");
UNREFERENCED_PARAMETER(pself);
return SANE_STATUS_GOOD;
}
@ -216,24 +172,15 @@ static SANE_Status SCSISource_init (SCSISource *pself, SnapScan_Scanner *pss)
SANE_Status status = Source_init ((Source *) pself, pss,
SCSISource_remaining,
Source_bytesPerLine,
Source_pixelsPerLine,
Source_pixelsPerLine,
SCSISource_get,
SCSISource_done);
SCSISource_done);
if (status == SANE_STATUS_GOOD)
{
pself->scsi_buf_max = 0;
pself->scsi_buf_pos = 0;
pself->absolute_max =
(SCANNER_BUF_SZ/pss->bytes_per_line)*pss->bytes_per_line;
if (gettimeofday(&(pself->time), NULL) != 0)
{
DBG (DL_MAJOR_ERROR,
"%s: error in gettimeofday(): %s\n",
__FUNCTION__,
strerror(errno));
pself->time.tv_sec = SCSISOURCE_BAD_TIME;
pself->time.tv_usec = SCSISOURCE_BAD_TIME;
}
(pss->phys_buf_sz/pss->bytes_per_line)*pss->bytes_per_line;
}
return status;
}
@ -258,35 +205,32 @@ static SANE_Status FDSource_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen)
SANE_Int remaining = *plen;
while (remaining > 0
&&
pself->remaining(pself) > 0
&&
status == SANE_STATUS_GOOD)
&& pself->remaining(pself) > 0
&& status == SANE_STATUS_GOOD)
{
SANE_Int bytes_read = read (ps->fd, pbuf, remaining);
if (bytes_read == -1)
{
if (errno == EAGAIN)
{
{
/* No data currently available */
break;
}
/* It's an IO error */
DBG (DL_MAJOR_ERROR,
"%s: read failed: %s\n",
__FUNCTION__,
strerror(errno));
/* It's an IO error */
DBG (DL_MAJOR_ERROR, "%s: read failed: %s\n",
__FUNCTION__, strerror(errno));
status = SANE_STATUS_IO_ERROR;
}
else if (bytes_read == 0)
{
{
/* EOF of current reading */
DBG(DL_DATA_TRACE, "%s: EOF\n",__FUNCTION__);
break;
}
}
ps->pss->bytes_remaining -= bytes_read;
remaining -= bytes_read;
pbuf += bytes_read;
}
*plen -= remaining;
return status;
}
@ -299,15 +243,15 @@ static SANE_Status FDSource_done (Source *pself)
static SANE_Status FDSource_init (FDSource *pself,
SnapScan_Scanner *pss,
int fd)
int fd)
{
SANE_Status status = Source_init ((Source *) pself,
pss,
FDSource_remaining,
Source_bytesPerLine,
Source_pixelsPerLine,
Source_pixelsPerLine,
FDSource_get,
FDSource_done);
FDSource_done);
if (status == SANE_STATUS_GOOD)
pself->fd = fd;
return status;
@ -339,7 +283,6 @@ static SANE_Status BufSource_get (Source *pself,
BufSource *ps = (BufSource *) pself;
SANE_Status status = SANE_STATUS_GOOD;
SANE_Int to_move = MIN(*plen, pself->remaining(pself));
if (to_move == 0)
{
status = SANE_STATUS_EOF;
@ -361,16 +304,17 @@ static SANE_Status BufSource_done (Source *pself)
static SANE_Status BufSource_init (BufSource *pself,
SnapScan_Scanner *pss,
SANE_Byte *buf,
SANE_Int buf_size)
SANE_Byte *buf,
SANE_Int buf_size)
{
SANE_Status status = Source_init ((Source *) pself,
pss,
pss,
BufSource_remaining,
Source_bytesPerLine,
Source_pixelsPerLine,
Source_pixelsPerLine,
BufSource_get,
BufSource_done);
BufSource_done);
DBG(DL_DATA_TRACE, "BufSource_init: buf_size=%d\n", buf_size);
if (status == SANE_STATUS_GOOD)
{
pself->buf = buf;
@ -398,10 +342,10 @@ static SANE_Status create_base_source (SnapScan_Scanner *pss,
status = SANE_STATUS_NO_MEM;
}
else
{
{
status = SCSISource_init ((SCSISource *) *pps, pss);
}
break;
break;
case FD_SRC:
*pps = (Source *) malloc(sizeof(FDSource));
if (*pps == NULL)
@ -410,10 +354,10 @@ static SANE_Status create_base_source (SnapScan_Scanner *pss,
status = SANE_STATUS_NO_MEM;
}
else
{
{
status = FDSource_init ((FDSource *) *pps, pss, pss->rpipe[0]);
}
break;
break;
case BUF_SRC:
*pps = (Source *) malloc(sizeof(BufSource));
if (*pps == NULL)
@ -422,13 +366,13 @@ static SANE_Status create_base_source (SnapScan_Scanner *pss,
status = SANE_STATUS_NO_MEM;
}
else
{
{
status = BufSource_init ((BufSource *) *pps,
pss,
pss->buf,
pss->read_bytes);
}
break;
break;
default:
DBG (DL_MAJOR_ERROR, "illegal base source type %d", st);
break;
@ -441,8 +385,8 @@ static SANE_Status create_base_source (SnapScan_Scanner *pss,
/* The transformer sources */
#define TX_SOURCE_GUTS \
SOURCE_GUTS;\
Source *psub /* sub-source */
SOURCE_GUTS;\
Source *psub /* sub-source */
typedef struct
{
@ -488,16 +432,16 @@ static SANE_Status TxSource_init (TxSource *pself,
SourceBytesPerLine bytesPerLine,
SourcePixelsPerLine pixelsPerLine,
SourceGet get,
SourceDone done,
Source *psub)
SourceDone done,
Source *psub)
{
SANE_Status status = Source_init((Source *) pself,
pss,
pss,
remaining,
bytesPerLine,
bytesPerLine,
pixelsPerLine,
get,
done);
done);
if (status == SANE_STATUS_GOOD)
pself->psub = psub;
return status;
@ -509,13 +453,13 @@ static SANE_Status TxSource_init (TxSource *pself,
typedef struct
{
TX_SOURCE_GUTS;
SANE_Byte *ch_buf; /* channel buffer */
SANE_Int ch_size; /* channel buffer size = #bytes in a channel */
SANE_Int ch_ndata; /* actual #bytes in channel buffer */
SANE_Int ch_pos; /* position in buffer */
SANE_Int bit; /* current bit */
SANE_Int last_bit; /* current last bit (counting down) */
SANE_Int last_last_bit; /* last bit in the last byte of the channel */
SANE_Byte *ch_buf; /* channel buffer */
SANE_Int ch_size; /* channel buffer size = #bytes in a channel */
SANE_Int ch_ndata; /* actual #bytes in channel buffer */
SANE_Int ch_pos; /* position in buffer */
SANE_Int bit; /* current bit */
SANE_Int last_bit; /* current last bit (counting down) */
SANE_Int last_last_bit; /* last bit in the last byte of the channel */
} Expander;
static SANE_Int Expander_remaining (Source *pself)
@ -587,9 +531,9 @@ static SANE_Status Expander_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen)
ps->last_bit = 0;
}
else
{
{
ps->bit--;
}
}
}
*plen -= remaining;
@ -608,8 +552,8 @@ static SANE_Status Expander_done (Source *pself)
}
static SANE_Status Expander_init (Expander *pself,
SnapScan_Scanner *pss,
Source *psub)
SnapScan_Scanner *pss,
Source *psub)
{
SANE_Status status = TxSource_init((TxSource *) pself,
pss,
@ -626,7 +570,7 @@ static SANE_Status Expander_init (Expander *pself,
if (pself->ch_buf == NULL)
{
DBG (DL_MAJOR_ERROR,
"%s: couldn't allocate channel buffer.\n",
"%s: couldn't allocate channel buffer.\n",
__FUNCTION__);
status = SANE_STATUS_NO_MEM;
}
@ -650,14 +594,14 @@ static SANE_Status Expander_init (Expander *pself,
static SANE_Status create_Expander (SnapScan_Scanner *pss,
Source *psub,
Source **pps)
Source **pps)
{
SANE_Status status = SANE_STATUS_GOOD;
*pps = (Source *) malloc(sizeof(Expander));
if (*pps == NULL)
{
DBG (DL_MAJOR_ERROR,
"%s: failed to allocate Expander.\n",
"%s: failed to allocate Expander.\n",
__FUNCTION__);
status = SANE_STATUS_NO_MEM;
}
@ -675,44 +619,27 @@ static SANE_Status create_Expander (SnapScan_Scanner *pss,
typedef struct
{
TX_SOURCE_GUTS;
SANE_Byte *cbuf; /* circular line buffer */
SANE_Byte *xbuf; /* single line buffer */
SANE_Int pos; /* current position in xbuf */
SANE_Int cb_size; /* size of the circular buffer */
SANE_Int cb_line_size; /* size of a line in the circular buffer */
SANE_Int cb_start; /* start of valid data in the circular buffer */
SANE_Int ch_offset[3]; /* offset in cbuf */
SANE_Byte *cbuf; /* circular line buffer */
SANE_Byte *xbuf; /* single line buffer */
SANE_Int pos; /* current position in xbuf */
SANE_Int cb_size; /* size of the circular buffer */
SANE_Int cb_line_size;/* size of a line in the circular buffer */
SANE_Int cb_start; /* start of valid data in the circular buffer */
SANE_Int cb_finish; /* finish of valid data, for next read */
SANE_Int ch_offset[3];/* offset in cbuf */
SANE_Int round_req;
SANE_Int round_read;
} RGBRouter;
static SANE_Int RGBRouter_remaining (Source *pself)
{
RGBRouter *ps = (RGBRouter *) pself;
SANE_Int remaining;
if (ps->cb_start < 0)
remaining = (TxSource_remaining(pself) - ps->cb_size + ps->cb_line_size);
SANE_Int remaining;
if (ps->round_req == ps->cb_size)
remaining = TxSource_remaining(pself) - ps->cb_size + ps->cb_line_size;
else
remaining = (TxSource_remaining(pself) + ps->cb_line_size - ps->pos);
if (remaining < 0)
{
/* We are in big trouble. Someone is using the RBGRouter routines
* to find out how much is remaining. There is a case were not
* enough data has been read yet to fill the circular buffer.
* Until it is filled then no one should be accessing it or
* checking how much is remaining (in current implemntation).
* FIXME: For now, there is some code (measure_transfer_rate) that
* will do this at times and setting remaining = 1 allows some
* scans to squeak by.
*/
remaining = 1;
DBG (DL_MAJOR_ERROR,
"%s: Computed a negative size for circular buffer! Forcing to size of 1 to keep going\n",
__FUNCTION__);
}
return (remaining);
remaining = TxSource_remaining(pself) + ps->cb_line_size - ps->pos;
return (remaining);
}
static SANE_Status RGBRouter_get (Source *pself,
@ -724,60 +651,76 @@ static SANE_Status RGBRouter_get (Source *pself,
SANE_Int remaining = *plen;
SANE_Byte *s;
SANE_Int i;
SANE_Int r;
SANE_Int g;
SANE_Int b;
SANE_Int r, g, b;
SANE_Int run_req;
SANE_Int org_len = *plen;
char *me = "RGBRouter_get";
while (remaining > 0 && pself->remaining(pself) > 0)
{
DBG(DL_DATA_TRACE, "%s: remaining=%d, pself->remaining=%d, round_req=%d, cb_size=%d\n",
me, remaining, pself->remaining(pself), ps->round_req, ps->cb_size);
/* Check if there is no valid data left from previous get */
if (ps->pos >= ps->cb_line_size)
{
/* Try to get more data */
SANE_Int ndata = (ps->cb_start < 0) ? ps->cb_size : (ps->cb_line_size - ps->cb_start%ps->cb_line_size);
SANE_Int start = (ps->cb_start < 0) ? 0 : ps->cb_start;
SANE_Int ndata2;
SANE_Int ndata3;
/* Try to get more data. either one line or
full buffer (first time) */
do
{
run_req = ps->round_req - ps->round_read;
status = TxSource_get (pself,
ps->cbuf + ps->cb_start + ps->round_read,
&run_req);
if (status != SANE_STATUS_GOOD || run_req==0)
{
*plen -= remaining;
if ( *plen > 0 )
DBG(DL_DATA_TRACE, "%s: request=%d, read=%d\n",
me, org_len, *plen);
return status;
}
ps->round_read += run_req;
}
while (ps->round_req > ps->round_read);
ndata2 = ndata;
ndata3 = 0;
do
{
status = TxSource_get (pself, ps->cbuf + start + ndata3, &ndata2);
if (status != SANE_STATUS_GOOD || ndata2 == 0)
{
DBG (DL_MINOR_ERROR,
"TxSource_get failed status:%d, ndata:%d, ndata2:%d ndata3:%d\n", status, ndata, ndata2, ndata3);
ps->cb_start = (start + ndata3)%ps->cb_size;
*plen -= remaining;
return status;
}
ndata3 += ndata2;
ndata2 = ndata - ndata3;
}
while (ndata3 < ndata);
ps->cb_start = (start + ndata3)%ps->cb_size;
s = ps->xbuf;
r = (ps->cb_start + ps->ch_offset[0])%ps->cb_size;
g = (ps->cb_start + ps->ch_offset[1])%ps->cb_size;
b = (ps->cb_start + ps->ch_offset[2])%ps->cb_size;
/* route RGB */
ps->cb_start = (ps->cb_start + ps->round_read)%ps->cb_size;
s = ps->xbuf;
r = (ps->cb_start + ps->ch_offset[0])%ps->cb_size;
g = (ps->cb_start + ps->ch_offset[1])%ps->cb_size;
b = (ps->cb_start + ps->ch_offset[2])%ps->cb_size;
for (i = 0; i < ps->cb_line_size/3; i++)
{
*s++ = ps->cbuf[r++];
*s++ = ps->cbuf[g++];
*s++ = ps->cbuf[b++];
}
ps->pos = 0;
{
*s++ = ps->cbuf[r++];
*s++ = ps->cbuf[g++];
*s++ = ps->cbuf[b++];
}
/* end of reading & offsetiing whole line data;
reset valid position */
ps->pos = 0;
/* prepare for next round */
ps->round_req = ps->cb_line_size;
ps->round_read =0;
}
/* Repack the whole scan line now */
while (remaining > 0 && ps->pos < ps->cb_line_size)
{
/* Repack the whole scan line and copy to caller's buffer */
while (remaining > 0 && ps->pos < ps->cb_line_size)
{
*pbuf++ = ps->xbuf[ps->pos++];
remaining--;
}
}
}
*plen -= remaining;
DBG(DL_DATA_TRACE,
"%s: Request=%d, remaining=%d, read=%d, TXSource_rem=%d, bytes_rem=%d\n",
me,
org_len,
pself->remaining(pself),
*plen,
TxSource_remaining(pself),
ps->pss->bytes_remaining);
return status;
}
@ -795,35 +738,31 @@ static SANE_Status RGBRouter_done (Source *pself)
}
static SANE_Status RGBRouter_init (RGBRouter *pself,
SnapScan_Scanner *pss,
Source *psub)
SnapScan_Scanner *pss,
Source *psub)
{
SANE_Status status = TxSource_init((TxSource *) pself,
pss,
RGBRouter_remaining,
TxSource_bytesPerLine,
TxSource_pixelsPerLine,
TxSource_pixelsPerLine,
RGBRouter_get,
RGBRouter_done,
psub);
RGBRouter_done,
psub);
if (status == SANE_STATUS_GOOD)
{
SANE_Int lines_in_buffer = 1;
SANE_Int ch;
/* Size the buffer to accomodate the necessary number of scan lines
to cater for the offset between R, G and B */
lines_in_buffer = 0;
for (ch = 0; ch < 3; ch++)
{
if (pss->chroma_offset[ch] > lines_in_buffer)
lines_in_buffer = pss->chroma_offset[ch];
}
lines_in_buffer++;
SANE_Int lines_in_buffer = 0;
/* Size the buffer to accomodate the necessary number of scan
lines to cater for the offset between R, G and B */
lines_in_buffer = pss->chroma + 1;
pself->cb_line_size = pself->bytesPerLine((Source *) pself);
pself->cb_size = pself->cb_line_size*lines_in_buffer;
pself->pos = pself->cb_line_size;
pself->round_req = pself->cb_size;
pself->round_read = 0;
pself->cbuf = (SANE_Byte *) malloc(pself->cb_size);
pself->xbuf = (SANE_Byte *) malloc(pself->cb_line_size);
if (pself->cbuf == NULL || pself->xbuf == NULL)
@ -837,27 +776,34 @@ static SANE_Status RGBRouter_init (RGBRouter *pself,
{
SANE_Int ch;
pself->cb_start = -1;
pself->cb_start = 0;
for (ch = 0; ch < 3; ch++)
{
pself->ch_offset[ch] = pss->chroma_offset[ch]*pself->bytesPerLine((Source *) pself)
+ ch*(pself->bytesPerLine((Source *) pself)/3);
pself->ch_offset[ch] =
pss->chroma_offset[ch] * pself->cb_line_size
+ ch * (pself->cb_line_size / 3);
}
}
DBG(DL_MINOR_INFO, "RGBRouter_init: buf_size: %d x %d = %d\n",
pself->cb_line_size, lines_in_buffer, pself->cb_size);
DBG(DL_MINOR_INFO, "RGBRouter_init: buf offset R:%d G:%d B:%d\n",
pself->ch_offset[0], pself->ch_offset[1],pself->ch_offset[2]);
}
return status;
}
static SANE_Status create_RGBRouter (SnapScan_Scanner *pss,
Source *psub,
Source **pps)
Source **pps)
{
static char me[] = "create_RGBRouter";
SANE_Status status = SANE_STATUS_GOOD;
DBG (DL_CALL_TRACE, "%s\n", me);
*pps = (Source *) malloc(sizeof(RGBRouter));
if (*pps == NULL)
{
DBG (DL_MAJOR_ERROR,
"%s: failed to allocate RGBRouter.\n",
DBG (DL_MAJOR_ERROR, "%s: failed to allocate RGBRouter.\n",
__FUNCTION__);
status = SANE_STATUS_NO_MEM;
}
@ -881,7 +827,6 @@ static SANE_Status Inverter_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen)
if (status == SANE_STATUS_GOOD)
{
int i;
for (i = 0; i < *plen; i++)
pbuf[i] ^= 0xFF;
}
@ -890,29 +835,28 @@ static SANE_Status Inverter_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen)
static SANE_Status Inverter_init (Inverter *pself,
SnapScan_Scanner *pss,
Source *psub)
Source *psub)
{
return TxSource_init ((TxSource *) pself,
pss,
TxSource_remaining,
TxSource_bytesPerLine,
TxSource_pixelsPerLine,
TxSource_pixelsPerLine,
Inverter_get,
TxSource_done,
psub);
TxSource_done,
psub);
}
static SANE_Status create_Inverter (SnapScan_Scanner *pss,
Source *psub,
Source **pps)
Source **pps)
{
SANE_Status status = SANE_STATUS_GOOD;
*pps = (Source *) malloc(sizeof(Inverter));
if (*pps == NULL)
{
DBG (DL_MAJOR_ERROR,
"%s: failed to allocate Inverter.\n",
__FUNCTION__);
DBG (DL_MAJOR_ERROR, "%s: failed to allocate Inverter.\n",
__FUNCTION__);
status = SANE_STATUS_NO_MEM;
}
else
@ -926,9 +870,12 @@ static SANE_Status create_Inverter (SnapScan_Scanner *pss,
static SANE_Status create_source_chain (SnapScan_Scanner *pss,
BaseSourceType bst,
Source **pps)
Source **pps)
{
static char me[] = "create_source_chain";
SANE_Status status = create_base_source (pss, bst, pps);
DBG (DL_CALL_TRACE, "%s\n", me);
if (status == SANE_STATUS_GOOD)
{
SnapScan_Mode mode = actual_mode(pss);
@ -952,10 +899,8 @@ static SANE_Status create_source_chain (SnapScan_Scanner *pss,
status = create_Inverter (pss, *pps, pps);
break;
default:
DBG (DL_MAJOR_ERROR,
"%s: bad mode value %d (internal error)\n",
__FUNCTION__,
mode);
DBG (DL_MAJOR_ERROR, "%s: bad mode value %d (internal error)\n",
__FUNCTION__, mode);
status = SANE_STATUS_INVAL;
break;
}
@ -965,10 +910,31 @@ static SANE_Status create_source_chain (SnapScan_Scanner *pss,
/*
* $Log$
* Revision 1.4 2001/05/26 12:47:31 hmg
* Updated snapscan backend to version 1.2 (from
* Sebastien Sable <Sebastien.Sable@snv.jussieu.fr>).
* Henning Meier-Geinitz <henning@meier-geinitz.de>
* Revision 1.5 2001/10/09 09:45:12 oliverschwartz
* update snapscan to snapshot 20011008
*
* Revision 1.16 2001/10/08 18:22:02 oliverschwartz
* - Disable quality calibration for Acer Vuego 310F
* - Use sanei_scsi_max_request_size as scanner buffer size
* for SCSI devices
* - Added new devices to snapscan.desc
*
* Revision 1.15 2001/09/28 15:56:51 oliverschwartz
* - fix hanging for SNAPSCAN300 / VUEGO 310
*
* Revision 1.14 2001/09/28 13:39:16 oliverschwartz
* - Added "Snapscan 300" ID string
* - cleanup
* - more debugging messages in snapscan-sources.c
*
* Revision 1.13 2001/09/18 15:01:07 oliverschwartz
* - Read scanner id string again after firmware upload
* to indentify correct model
* - Make firmware upload work for AGFA scanners
* - Change copyright notice
*
* Revision 1.12 2001/09/09 18:06:32 oliverschwartz
* add changes from Acer (new models; automatic firmware upload for USB scanners); fix distorted colour scans after greyscale scans (call set_window only in sane_start); code cleanup
*
* Revision 1.11 2001/04/13 13:12:18 oliverschwartz
* use absolute_max as expected_read_bytes for PRISA620S

Wyświetl plik

@ -2,7 +2,8 @@
Copyright (C) 1997, 1998 Franck Schnefra, Michel Roelofs,
Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller,
Petter Reinholdtsen, Gary Plewa, Sebastien Sable and Kevin Charter
Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Oliver Schwartz
and Kevin Charter
This file is part of the SANE package.
@ -87,10 +88,14 @@ static SANE_Status Source_init (Source *pself,
/*
* $Log$
* Revision 1.3 2001/05/26 12:47:31 hmg
* Updated snapscan backend to version 1.2 (from
* Sebastien Sable <Sebastien.Sable@snv.jussieu.fr>).
* Henning Meier-Geinitz <henning@meier-geinitz.de>
* Revision 1.4 2001/10/09 09:45:13 oliverschwartz
* update snapscan to snapshot 20011008
*
* Revision 1.4 2001/09/18 15:01:07 oliverschwartz
* - Read scanner id string again after firmware upload
* to indentify correct model
* - Make firmware upload work for AGFA scanners
* - Change copyright notice
*
* Revision 1.3 2001/03/17 22:53:21 sable
* Applying Mikael Magnusson patch concerning Gamma correction

Wyświetl plik

@ -25,7 +25,7 @@
History
0.1 2000-02-01
0.1 2000-02-01
First version released
@ -47,8 +47,11 @@
So far this strategy has worked flawlessly. Thanks Dmitri!
*/
#include <sys/ipc.h>
#include <sys/sem.h>
/* $Id$
SnapScan backend scan data sources */
#include <sys/ipc.h>
#include <sys/sem.h>
#include "snapscan-usb.h"
@ -59,48 +62,48 @@ static struct sembuf sem_wait = { 0, -1, 0 };
static struct sembuf sem_signal = { 0, 1, 0 };
static SANE_Status snapscani_usb_cmd(int fd, const void *src, size_t src_size,
void *dst, size_t * dst_size)
void *dst, size_t * dst_size)
{
static const char me[] = "snapscani_usb_cmd";
int status;
DBG (DL_CALL_TRACE, "%s(%d,0x%x,%d,0x%x,0x%x (%d))\n", me,
fd,(int)src,src_size,(int)dst,(int)dst_size,dst_size ? *dst_size : 0);
fd,(int)src,src_size,(int)dst,(int)dst_size,dst_size ? *dst_size : 0);
while(bqhead) {
status = atomic_usb_cmd(fd, bqhead->src, bqhead->src_size, NULL, NULL);
if(status == SANE_STATUS_DEVICE_BUSY) {
if(is_queueable(src)) {
enqueue_bq(fd,src,src_size);
return SANE_STATUS_GOOD;
} else {
sleep(1);
continue;
}
}
dequeue_bq();
status = atomic_usb_cmd(fd, bqhead->src, bqhead->src_size, NULL, NULL);
if(status == SANE_STATUS_DEVICE_BUSY) {
if(is_queueable(src)) {
enqueue_bq(fd,src,src_size);
return SANE_STATUS_GOOD;
} else {
sleep(1);
continue;
}
}
dequeue_bq();
}
status = atomic_usb_cmd(fd,src,src_size,dst,dst_size);
if((status == SANE_STATUS_DEVICE_BUSY) && is_queueable(src) ) {
enqueue_bq(fd,src,src_size);
return SANE_STATUS_GOOD;
if ((status == SANE_STATUS_DEVICE_BUSY) && is_queueable(src) ) {
enqueue_bq(fd,src,src_size);
return SANE_STATUS_GOOD;
}
return status;
return status;
}
static SANE_Status atomic_usb_cmd(int fd, const void *src, size_t src_size,
void *dst, size_t * dst_size)
void *dst, size_t * dst_size)
{
static const char me[] = "atomic_usb_cmd";
int status;
sigset_t all,oldset;
DBG (DL_CALL_TRACE, "%s(%d,0x%x,%d,0x%x,0x%x (%d))\n", me,
fd,(int)src,src_size,(int)dst,(int)dst_size,dst_size ? *dst_size : 0);
fd,(int)src,src_size,(int)dst,(int)dst_size,dst_size ? *dst_size : 0);
/* Prevent the calling process from being killed */
sigfillset(&all);
@ -115,15 +118,14 @@ static SANE_Status atomic_usb_cmd(int fd, const void *src, size_t src_size,
/* Now it is ok to be killed */
sigprocmask(SIG_SETMASK, &oldset, NULL);
return status;
return status;
}
static SANE_Status snapscani_usb_open(const char *dev, int *fdp,
SANEI_SCSI_Sense_Handler handler, void *handler_arg)
static SANE_Status snapscani_usb_open(const char *dev, int *fdp)
{
return usb_open(dev,fdp,handler,handler_arg);
return usb_open(dev,fdp);
}
@ -142,12 +144,12 @@ static int usb_cmdlen(int cmd)
case RESERVE_UNIT:
case RELEASE_UNIT:
case SEND_DIAGNOSTIC:
return 6;
return 6;
case SEND:
case SET_WINDOW:
case READ:
case GET_DATA_BUFFER_STATUS:
return 10;
return 10;
}
return 0;
}
@ -158,42 +160,41 @@ static char *usb_debug_data(char *str,const char *data, int len) {
str[0]=0;
for(i=0; i < (len < 10 ? len : 10); i++) {
sprintf(tmpstr," 0x%02x",((int)data[i]) & 0xff);
if(i%16 == 0 && i != 0)
strcat(str,"\n");
strcat(str,tmpstr);
sprintf(tmpstr," 0x%02x",((int)data[i]) & 0xff);
if(i%16 == 0 && i != 0)
strcat(str,"\n");
strcat(str,tmpstr);
}
if(i < len)
strcat(str," ...");
strcat(str," ...");
return str;
}
static SANE_Status usb_open(const char *dev, int *fdp,
SANEI_SCSI_Sense_Handler handler, void *handler_arg)
static SANE_Status usb_open(const char *dev, int *fdp)
{
static const char me[] = "usb_open";
DBG (DL_CALL_TRACE, "%s(%s)\n", me, dev);
static const char me[] = "usb_open";
if((sem_id = semget( ftok(dev,0x1234), 1, IPC_CREAT | 0660 )) == -1) {
DBG (DL_MAJOR_ERROR, "%s: Can't get semaphore\n", me);
return SANE_STATUS_INVAL;
}
semop(sem_id, &sem_signal, 1);
DBG (DL_CALL_TRACE, "%s(%s)\n", me, dev);
*fdp = open(dev, O_RDWR);
if( *fdp < 0)
return SANE_STATUS_INVAL;
return SANE_STATUS_GOOD;
if((sem_id = semget( ftok(dev,0x1234), 1, IPC_CREAT | 0660 )) == -1) {
DBG (DL_MAJOR_ERROR, "%s: Can't get semaphore\n", me);
return SANE_STATUS_INVAL;
}
semop(sem_id, &sem_signal, 1);
*fdp = open(dev, O_RDWR);
if( *fdp < 0)
return SANE_STATUS_INVAL;
return SANE_STATUS_GOOD;
}
static void usb_close(int fd) {
static const char me[] = "usb_close";
DBG (DL_CALL_TRACE, "%s(%d)\n", me, fd);
semctl(sem_id, 0, IPC_RMID, 0);
close(fd);
static const char me[] = "usb_close";
DBG (DL_CALL_TRACE, "%s(%d)\n", me, fd);
semctl(sem_id, 0, IPC_RMID, 0);
close(fd);
}
/*
@ -204,12 +205,12 @@ static int usb_status(char *status_buf) {
switch(status) {
case GOOD:
return SANE_STATUS_GOOD;
return SANE_STATUS_GOOD;
case CHECK_CONDITION:
case BUSY:
return SANE_STATUS_DEVICE_BUSY;
return SANE_STATUS_DEVICE_BUSY;
default:
return SANE_STATUS_IO_ERROR;
return SANE_STATUS_IO_ERROR;
}
}
*/
@ -219,13 +220,13 @@ static int usb_status(char *status_buf) {
static SANE_Status usb_write(int fd, const void *buf, int n) {
char dbgmsg[16384];
int r;
static const char me[] = "usb_write";
DBG(DL_DATA_TRACE, "%s: writing: %s\n",me,usb_debug_data(dbgmsg,buf,n));
if((r=write(fd,buf,n)) != n) {
DBG (DL_MAJOR_ERROR, "%s Only %d bytes written\n",me,r);
return SANE_STATUS_IO_ERROR;
DBG (DL_MAJOR_ERROR, "%s Only %d bytes written\n",me,r);
return SANE_STATUS_IO_ERROR;
}
return SANE_STATUS_GOOD;
}
@ -233,7 +234,7 @@ static SANE_Status usb_write(int fd, const void *buf, int n) {
static SANE_Status usb_read(int fd, void *buf, int n) {
char dbgmsg[16384];
int r;
static const char me[] = "usb_read";
/* USB driver appears to block in all cases when asking for data
@ -245,13 +246,13 @@ static SANE_Status usb_read(int fd, void *buf, int n) {
do
{
if((r=read(fd,buf,n)) != n && !(r == -1 && errno == EAGAIN)) {
DBG (DL_MAJOR_ERROR, "%s Only %d bytes read\n",me,r);
return SANE_STATUS_IO_ERROR;
DBG (DL_MAJOR_ERROR, "%s Only %d bytes read\n",me,r);
return SANE_STATUS_IO_ERROR;
}
if (r == -1 && errno == EAGAIN)
{
DBG (DL_MAJOR_ERROR, "%s: Got an EAGAIN\n",me);
usleep(10000);
DBG (DL_MAJOR_ERROR, "%s: Got an EAGAIN\n",me);
usleep(10000);
}
} while (r == -1 && errno == EAGAIN);
@ -260,40 +261,40 @@ static SANE_Status usb_read(int fd, void *buf, int n) {
}
static SANE_Status usb_read_status(int fd, int *scsistatus, int *transaction_status)
{
{
unsigned char status_buf[8];
int scsistat;
int status;
RETURN_ON_FAILURE(usb_read(fd,status_buf,8));
if(transaction_status)
*transaction_status = status_buf[0];
*transaction_status = status_buf[0];
scsistat = (status_buf[1] & STATUS_MASK) >> 1;
if(scsistatus)
*scsistatus = scsistat;
*scsistatus = scsistat;
switch(scsistat) {
case GOOD:
return SANE_STATUS_GOOD;
return SANE_STATUS_GOOD;
case CHECK_CONDITION:
case BUSY:
return SANE_STATUS_DEVICE_BUSY;
return SANE_STATUS_DEVICE_BUSY;
default:
return SANE_STATUS_IO_ERROR;
return SANE_STATUS_IO_ERROR;
}
}
static SANE_Status usb_cmd(int fd, const void *src, size_t src_size,
void *dst, size_t * dst_size)
void *dst, size_t * dst_size)
{
static const char me[] = "usb_cmd";
int status,tstatus;
int cmdlen,datalen;
DBG (DL_CALL_TRACE, "%s(%d,0x%x,%d,0x%x,0x%x (%d))\n", me,
fd,(int)src,src_size,(int)dst,(int)dst_size,dst_size ? *dst_size : 0);
@ -303,7 +304,7 @@ static SANE_Status usb_cmd(int fd, const void *src, size_t src_size,
*/
if(((char *)src)[0] == SEND_DIAGNOSTIC)
return(SANE_STATUS_GOOD);
cmdlen = usb_cmdlen(*((char *)src));
datalen = src_size - cmdlen;
@ -317,7 +318,7 @@ static SANE_Status usb_cmd(int fd, const void *src, size_t src_size,
/* Send data only if the scanner is expecting it */
if(datalen > 0 && (tstatus == TRANSACTION_WRITE)) {
/* Send data to scanner */
/* Send data to scanner */
RETURN_ON_FAILURE( usb_write(fd, ((SANE_Byte *) src) + cmdlen, datalen) );
/* Read status */
@ -334,14 +335,14 @@ static SANE_Status usb_cmd(int fd, const void *src, size_t src_size,
if(tstatus != TRANSACTION_COMPLETED) {
if(tstatus == TRANSACTION_WRITE)
DBG(DL_MAJOR_ERROR,
"%s: The transaction should now be completed, but the scanner is expecting more data" ,me);
DBG(DL_MAJOR_ERROR,
"%s: The transaction should now be completed, but the scanner is expecting more data" ,me);
else
DBG(DL_MAJOR_ERROR,
"%s: The transaction should now be completed, but the scanner has more data to send" ,me);
DBG(DL_MAJOR_ERROR,
"%s: The transaction should now be completed, but the scanner has more data to send" ,me);
return SANE_STATUS_IO_ERROR;
}
return status;
}
@ -353,9 +354,9 @@ static int is_queueable(const char *src)
case SEND:
case SET_WINDOW:
case SEND_DIAGNOSTIC:
return 1;
return 1;
default:
return 0;
return 0;
}
}
@ -366,14 +367,14 @@ static int enqueue_bq(int fd,const void *src, size_t src_size)
{
static const char me[] = "enqueue_bq";
struct usb_busy_queue *bqe;
DBG (DL_CALL_TRACE, "%s(%d,%p,%d)\n", me, fd,src,src_size);
if((bqe = malloc(sizeof(struct usb_busy_queue))) == NULL)
return -1;
return -1;
if((bqe->src = malloc(src_size)) == NULL)
return -1;
return -1;
memcpy(bqe->src,src,src_size);
bqe->src_size=src_size;
@ -381,18 +382,18 @@ static int enqueue_bq(int fd,const void *src, size_t src_size)
bqe->next=NULL;
if(bqtail) {
bqtail->next=bqe;
bqtail = bqe;
bqtail->next=bqe;
bqtail = bqe;
} else
bqhead = bqtail = bqe;
bqhead = bqtail = bqe;
bqelements++;
DBG(DL_DATA_TRACE, "%s: Busy queue: elements=%d, bqhead=%p, bqtail=%p\n",
me,bqelements,bqhead,bqtail);
me,bqelements,bqhead,bqtail);
return 0;
}
static void dequeue_bq()
static void dequeue_bq()
{
static const char me[] = "dequeue_bq";
struct usb_busy_queue *tbqe;
@ -400,19 +401,31 @@ static void dequeue_bq()
DBG (DL_CALL_TRACE, "%s()\n", me);
if(!bqhead)
return;
return;
tbqe = bqhead;
bqhead = bqhead->next;
if(!bqhead)
bqtail=NULL;
bqtail=NULL;
if(tbqe->src)
free(tbqe->src);
free(tbqe->src);
free(tbqe);
bqelements--;
DBG(DL_DATA_TRACE, "%s: Busy queue: elements=%d, bqhead=%p, bqtail=%p\n",
me,bqelements,bqhead,bqtail);
me,bqelements,bqhead,bqtail);
}
/*
* $Log$
* Revision 1.2 2001/10/09 09:45:14 oliverschwartz
* update snapscan to snapshot 20011008
*
* Revision 1.12 2001/09/18 15:01:07 oliverschwartz
* - Read scanner id string again after firmware upload
* to indentify correct model
* - Make firmware upload work for AGFA scanners
* - Change copyright notice
*
* */

Wyświetl plik

@ -1,10 +1,38 @@
/*
Snapscan 1212U modifications for the Snapscan SANE backend
Copyright (C) 2000 Henrik Johansson
Henrik Johansson (henrikjo@post.urfors.se)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
This file implements USB equivalents to the SCSI routines used by the Snapscan
backend.
*/
/* $Id$
SnapScan backend scan data sources */
#ifndef snapscan_usb_h
#define snapscan_usb_h
static SANE_Status snapscani_usb_cmd(int fd, const void *src, size_t src_size,
void *dst, size_t * dst_size);
static SANE_Status snapscani_usb_open(const char *dev, int *fdp,
SANEI_SCSI_Sense_Handler handler, void *handler_arg);
void *dst, size_t * dst_size);
static SANE_Status snapscani_usb_open(const char *dev, int *fdp);
static void snapscani_usb_close(int fd);
/*
@ -46,13 +74,25 @@ static void dequeue_bq(void);
static int is_queueable(const char *src);
static SANE_Status atomic_usb_cmd(int fd, const void *src, size_t src_size,
void *dst, size_t * dst_size);
static SANE_Status usb_open(const char *dev, int *fdp,
SANEI_SCSI_Sense_Handler handler, void *handler_arg);
void *dst, size_t * dst_size);
static SANE_Status usb_open(const char *dev, int *fdp);
static void usb_close(int fd);
static SANE_Status usb_cmd(int fd, const void *src, size_t src_size,
void *dst, size_t * dst_size);
void *dst, size_t * dst_size);
#endif
/*
* $Log$
* Revision 1.2 2001/10/09 09:45:15 oliverschwartz
* update snapscan to snapshot 20011008
*
* Revision 1.8 2001/09/18 15:01:07 oliverschwartz
* - Read scanner id string again after firmware upload
* to indentify correct model
* - Make firmware upload work for AGFA scanners
* - Change copyright notice
*
* */

Plik diff jest za duży Load Diff

Wyświetl plik

@ -1,9 +1,14 @@
scsi AGFA
scsi COLOR
scsi ACERPERI
# If not automatically found from above, then you may manually specify
# a device name.
/dev/scanner
#/dev/usbscanner
# For USB devices, make sure that the name contains 'usb' somewhere, as in
# '/dev/usbscanner' or '/dev/usb/scanner0'. Do not use a link
# from /dev/scanner to your USB device.
/dev/usbscanner
#/dev/scanner
#/dev/sga
# Change to the fully qualified filename of your firmware file, if
# firmware upload is needed by the scanner
firmware /path/to/your/firmware/file

Wyświetl plik

@ -12,7 +12,7 @@
:backend "SnapScan" ; name of backend
:version "1.2" ; version of backend
:status :alpha ; :alpha, :beta, :stable, :new
:status :beta ; :alpha, :beta, :stable, :new
:manpage "sane-snapscan" ; name of manpage (if it exists)
:url "http://snapscan.sourceforge.net/" ; backend's web page
@ -40,10 +40,18 @@
:interface "SCSI"
:comment "Ditto. Have no specific programming info yet."
:model "SnapScan 1236u"
:interface "USB"
:comment "Ditto. Have no specific programming info yet."
:model "SnapScan 1212u"
:interface "USB"
:comment "Ditto. Have no specific programming info yet."
:model "SnapScan e20"
:interface "USB"
:comment "Have no specific programming info yet."
:model "SnapScan e40"
:interface "USB"
:comment "Have no specific programming info yet."
@ -52,6 +60,10 @@
:interface "USB"
:comment "Have no specific programming info yet."
:model "SnapScan e60"
:interface "USB"
:comment "Have no specific programming info yet."
:mfg "Vuego"
;------------------------------------------------------------------------------
@ -84,6 +96,10 @@
:interface "USB"
:comment "Seems to be a close SnapScan 310/600 compatible."
:model "Prisa 620ut"
:interface "USB"
:comment "Seems to be a close SnapScan 310/600 compatible."
:model "Prisa 640u"
:interface "USB"
:comment "Seems to be a close SnapScan 310/600 compatible."
@ -92,6 +108,22 @@
:interface "USB"
:comment "Seems to be a close SnapScan 310/600 compatible."
:model "Prisa 1240"
:interface "USB"
:comment "Seems to be a close SnapScan 310/600 compatible."
:model "Prisa 3300"
:interface "USB"
:comment "Seems to be a close SnapScan 310/600 compatible."
:model "Prisa 4300"
:interface "USB"
:comment "Seems to be a close SnapScan 310/600 compatible."
:model "Prisa 5300"
:interface "USB"
:comment "Seems to be a close SnapScan 310/600 compatible."
:mfg "Guillemot International"
;------------------------------------------------------------------------------

Wyświetl plik

@ -2,9 +2,9 @@
Copyright (C) 1997, 1998, 1999, 2001 Franck Schnefra, Michel Roelofs,
Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller,
Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Mikael Magnusson
and Kevin Charter
Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Mikael Magnusson,
Oliver Schwartz and Kevin Charter
This file is part of the SANE package.
This program is free software; you can redistribute it and/or
@ -42,7 +42,7 @@
If you write modifications of your own for SANE, it is your choice
whether to permit this exception to apply to your modifications.
If you do not wish that, delete this exception notice.
This file is a component of the implementation of a backend for many
of the the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */
@ -58,13 +58,14 @@
#define DEFAULT_DEVICE "/dev/scanner" /* Check this if config is missing */
#define SNAPSCAN_TYPE "flatbed scanner"
/*#define INOPERATIVE*/
#define TMP_FILE_PREFIX "/var/tmp/snapscan"
#define SNAPSCAN_CONFIG_FILE "snapscan.conf"
#define FIRMWARE_KW "firmware"
/* Define the colour channel order in arrays */
#define R_CHAN 0
#define G_CHAN 1
#define B_CHAN 2
#define R_CHAN 0
#define G_CHAN 1
#define B_CHAN 2
typedef enum
{
@ -76,16 +77,21 @@ typedef enum
typedef enum
{
UNKNOWN,
SNAPSCAN300, /* the original SnapScan or SnapScan 300 */
SNAPSCAN310, /* the SnapScan 310 */
SNAPSCAN600, /* the SnapScan 600 */
SNAPSCAN1236S, /* the SnapScan 1236s */
SNAPSCAN300, /* the original SnapScan or SnapScan 300 */
SNAPSCAN310, /* the SnapScan 310 */
SNAPSCAN600, /* the SnapScan 600 */
SNAPSCAN1236, /* the SnapScan 1236 */
SNAPSCAN1212U,
SNAPSCANE50, /* SnapScan e20/e40/e50 */
SNAPSCANE50, /* SnapScan e20/e40/e50 */
ACER300F,
VUEGO310S, /* Vuego-Version of SnapScan 310 WG changed */
VUEGO610S, /* Vuego 610S and 610plus SJU changed */
PRISA620S /* Prisa-Version of SnapScan 600 GP added */
VUEGO310S, /* Vuego-Version of SnapScan 310 WG changed */
VUEGO610S, /* Vuego 610S and 610plus SJU changed */
PRISA620S, /* Acer ScanPrisa 620 - 600 DPI */
PRISA640, /* Acer ScanPrisa 640 - 600 DPI */
PRISA4300, /* Acer ScanPrisa 3300/4300 - 600 DPI */
PRISA4300_2, /* Acer ScanPrisa 3300/4300 - 600 DPI */
PRISA1240, /* Acer ScanPrisa 1240 - 1200 DPI */
PRISA5300 /* Acer ScanPrisa 5300 - 1200 DPI */
} SnapScan_Model;
struct SnapScan_Model_desc
{
@ -96,24 +102,31 @@ struct SnapScan_Model_desc
static struct SnapScan_Model_desc scanners[] =
{
/* SCSI model name -> enum value */
{"FlatbedScanner_2", VUEGO610S},
{"FlatbedScanner_4", VUEGO310S},
{"FlatbedScanner_9", PRISA620S},
{"FlatbedScanner13", PRISA620S},
{"FlatbedScanner16", PRISA620S},
{"FlatbedScanner18", PRISA620S},
{"FlatbedScanner19", PRISA620S}, /* Acer ScanPrisa 1240UT */
{"FlatbedScanner20", PRISA620S},
{"SNAPSCAN 1212U", SNAPSCAN1212U},
{"SNAPSCAN 1212U_2", SNAPSCAN1212U},
{"SNAPSCAN e20", SNAPSCANE50},
{"SNAPSCAN e50", SNAPSCANE50},
{"SNAPSCAN e40", SNAPSCANE50},
{"SNAPSCAN 1236", SNAPSCAN1236S},
{"SNAPSCAN 310", SNAPSCAN310},
{"SNAPSCAN 600", SNAPSCAN600},
{"SnapScan", SNAPSCAN300},
{"ACERSCAN_A4____1", ACER300F},
{"FlatbedScanner_2", VUEGO610S},
{"FlatbedScanner_4", VUEGO310S},
{"FlatbedScanner_5", PRISA620S},
{"FlatbedScanner_9", PRISA620S},
{"FlatbedScanner13", PRISA620S},
{"FlatbedScanner16", PRISA620S},
{"FlatbedScanner17", PRISA620S},
{"FlatbedScanner18", PRISA620S},
{"FlatbedScanner19", PRISA1240},
{"FlatbedScanner20", PRISA640},
{"FlatbedScanner21", PRISA4300},
{"FlatbedScanner23", PRISA4300_2},
{"FlatbedScanner24", PRISA5300},
{"SNAPSCAN 1212U", SNAPSCAN1212U},
{"SNAPSCAN 1212U_2", SNAPSCAN1212U},
{"SNAPSCAN e20", SNAPSCANE50},
{"SNAPSCAN e50", SNAPSCANE50},
{"SNAPSCAN e40", SNAPSCANE50},
{"SNAPSCAN 1236", SNAPSCAN1236},
{"SNAPSCAN 1236U", SNAPSCAN1236},
{"SNAPSCAN 300", SNAPSCAN300},
{"SNAPSCAN 310", SNAPSCAN310},
{"SNAPSCAN 600", SNAPSCAN600},
{"SnapScan", SNAPSCAN300},
{"ACERSCAN_A4____1", ACER300F}
};
#define known_scanners ((int) (sizeof(scanners)/sizeof(scanners[0])))
@ -122,52 +135,53 @@ static char *vendors[] =
/* SCSI Vendor name */
"AGFA",
"COLOR",
"Color",
"ACERPER"
};
#define known_vendors ((int) (sizeof(vendors)/sizeof(vendors[0])))
typedef enum
{
OPT_COUNT = 0, /* option count */
OPT_MODE_GROUP, /* scan mode group */
OPT_SCANRES, /* scan resolution */
OPT_PREVIEW, /* preview mode toggle */
OPT_MODE, /* scan mode */
OPT_PREVIEW_MODE, /* preview mode */
OPT_SOURCE, /* scan source (flatbed / TPO) */
OPT_GEOMETRY_GROUP, /* geometry group */
OPT_TLX, /* top left x */
OPT_TLY, /* top left y */
OPT_BRX, /* bottom right x */
OPT_BRY, /* bottom right y */
OPT_PREDEF_WINDOW, /* predefined window configuration */
OPT_ENHANCEMENT_GROUP, /* enhancement group */
OPT_QUALITY_CAL, /* quality calibration */
OPT_HALFTONE, /* halftone flag */
OPT_HALFTONE_PATTERN, /* halftone matrix */
OPT_CUSTOM_GAMMA, /* use custom gamma tables */
OPT_COUNT = 0, /* option count */
OPT_MODE_GROUP, /* scan mode group */
OPT_SCANRES, /* scan resolution */
OPT_PREVIEW, /* preview mode toggle */
OPT_MODE, /* scan mode */
OPT_PREVIEW_MODE, /* preview mode */
OPT_SOURCE, /* scan source (flatbed / TPO) */
OPT_GEOMETRY_GROUP, /* geometry group */
OPT_TLX, /* top left x */
OPT_TLY, /* top left y */
OPT_BRX, /* bottom right x */
OPT_BRY, /* bottom right y */
OPT_PREDEF_WINDOW, /* predefined window configuration */
OPT_ENHANCEMENT_GROUP, /* enhancement group */
OPT_QUALITY_CAL, /* quality calibration */
OPT_HALFTONE, /* halftone flag */
OPT_HALFTONE_PATTERN, /* halftone matrix */
OPT_CUSTOM_GAMMA, /* use custom gamma tables */
OPT_GAMMA_BIND,
OPT_GAMMA_GS, /* gamma correction (greyscale) */
OPT_GAMMA_R, /* gamma correction (red) */
OPT_GAMMA_G, /* gamma correction (green) */
OPT_GAMMA_B, /* gamma correction (blue) */
OPT_GAMMA_VECTOR_GS, /* gamma correction vector (greyscale) */
OPT_GAMMA_VECTOR_R, /* gamma correction vector (red) */
OPT_GAMMA_VECTOR_G, /* gamma correction vector (green) */
OPT_GAMMA_VECTOR_B, /* gamma correction vector (blue) */
OPT_NEGATIVE, /* swap black and white */
OPT_THRESHOLD, /* threshold for line art */
OPT_BRIGHTNESS, /* brightness */
OPT_CONTRAST, /* contrast */
OPT_ADVANCED_GROUP, /* advanced group */
OPT_RGB_LPR, /* lines per scsi read (RGB) */
OPT_GS_LPR, /* lines per scsi read (GS) */
OPT_SCSI_CMDS, /* a group */
OPT_INQUIRY, /* inquiry command (button) */
OPT_SELF_TEST, /* self test command (button) */
OPT_REQ_SENSE, /* request sense command (button) */
OPT_REL_UNIT, /* release unit command (button) */
NUM_OPTS /* dummy (gives number of options) */
OPT_GAMMA_GS, /* gamma correction (greyscale) */
OPT_GAMMA_R, /* gamma correction (red) */
OPT_GAMMA_G, /* gamma correction (green) */
OPT_GAMMA_B, /* gamma correction (blue) */
OPT_GAMMA_VECTOR_GS, /* gamma correction vector (greyscale) */
OPT_GAMMA_VECTOR_R, /* gamma correction vector (red) */
OPT_GAMMA_VECTOR_G, /* gamma correction vector (green) */
OPT_GAMMA_VECTOR_B, /* gamma correction vector (blue) */
OPT_NEGATIVE, /* swap black and white */
OPT_THRESHOLD, /* threshold for line art */
OPT_BRIGHTNESS, /* brightness */
OPT_CONTRAST, /* contrast */
OPT_ADVANCED_GROUP, /* advanced group */
OPT_RGB_LPR, /* lines per scsi read (RGB) */
OPT_GS_LPR, /* lines per scsi read (GS) */
OPT_SCSI_CMDS, /* a group */
OPT_INQUIRY, /* inquiry command (button) */
OPT_SELF_TEST, /* self test command (button) */
OPT_REQ_SENSE, /* request sense command (button) */
OPT_REL_UNIT, /* release unit command (button) */
NUM_OPTS /* dummy (gives number of options) */
} SnapScan_Options;
typedef union
@ -181,41 +195,41 @@ Option_Value;
typedef enum
{
MD_COLOUR = 0, /* full colour */
MD_BILEVELCOLOUR, /* 1-bit per channel colour */
MD_GREYSCALE, /* grey scale */
MD_LINEART, /* black and white */
MD_COLOUR = 0, /* full colour */
MD_BILEVELCOLOUR, /* 1-bit per channel colour */
MD_GREYSCALE, /* grey scale */
MD_LINEART, /* black and white */
MD_NUM_MODES
} SnapScan_Mode;
typedef enum
{
SRC_FLATBED = 0, /* Flatbed (normal) */
SRC_TPO /* Transparency unit */
SRC_FLATBED = 0, /* Flatbed (normal) */
SRC_TPO /* Transparency unit */
} SnapScan_Source;
typedef enum
{
ST_IDLE, /* between scans */
ST_SCAN_INIT, /* scan initialization */
ST_SCANNING, /* actively scanning data */
ST_CANCEL_INIT /* cancellation begun */
ST_IDLE, /* between scans */
ST_SCAN_INIT, /* scan initialization */
ST_SCANNING, /* actively scanning data */
ST_CANCEL_INIT /* cancellation begun */
} SnapScan_State;
typedef struct snapscan_device
{
SANE_Device dev;
SANE_Range x_range; /* x dimension of scan area */
SANE_Range y_range; /* y dimension of scan area */
SnapScan_Model model; /* type of scanner */
SnapScan_Bus bus; /* bus of the device usb/scsi */
u_char *depths; /* bit depth table */
SANE_Range x_range; /* x dimension of scan area */
SANE_Range y_range; /* y dimension of scan area */
SnapScan_Model model; /* type of scanner */
SnapScan_Bus bus; /* bus of the device usb/scsi */
u_char *depths; /* bit depth table */
struct snapscan_device *pnext;
}
SnapScan_Device;
#define MAX_SCSI_CMD_LEN 256 /* not that large */
#define SCANNER_BUF_SZ 31744
#define MAX_SCSI_CMD_LEN 256 /* not that large */
#define DEFAULT_SCANNER_BUF_SZ 1024*63
typedef struct snapscan_scanner SnapScan_Scanner;
@ -223,81 +237,107 @@ typedef struct snapscan_scanner SnapScan_Scanner;
struct snapscan_scanner
{
SANE_String devname; /* the scsi device name */
SnapScan_Device *pdev; /* the device */
int fd; /* scsi file descriptor */
int opens; /* open count */
SANE_String tmpfname; /* temporary file name */
int tfd; /* temp file descriptor */
int rpipe[2]; /* reader pipe descriptors */
int orig_rpipe_flags; /* initial reader pipe flags */
pid_t child; /* child reader process pid */
SnapScan_Mode mode; /* mode */
SnapScan_Mode preview_mode; /* preview mode */
SnapScan_Source source; /* scanning source */
SnapScan_State state; /* scanner state */
u_char cmd[MAX_SCSI_CMD_LEN]; /* scsi command buffer */
u_char buf[SCANNER_BUF_SZ]; /* data buffer */
size_t buf_sz; /* effective buffer size */
size_t expected_read_bytes; /* expected amount of data in a single read */
size_t read_bytes; /* amount of actual data read */
size_t bytes_remaining; /* remaining bytes expected from scanner */
size_t actual_res; /* actual resolution */
size_t lines; /* number of scan lines */
size_t bytes_per_line; /* bytes per scan line */
size_t pixels_per_line; /* pixels per scan line */
u_char hconfig; /* hardware configuration byte */
float ms_per_line; /* speed: milliseconds per scan line */
SANE_Bool nonblocking; /* wait on reads for data? */
char *sense_str; /* sense string */
char *as_str; /* additional sense string */
u_char asi1; /* first additional sense info byte */
u_char asi2; /* second additional sense info byte */
SANE_Byte chroma_offset[3]; /* chroma offsets */
Source *psrc; /* data source */
SANE_String devname; /* the scsi device name */
SnapScan_Device *pdev; /* the device */
int fd; /* scsi file descriptor */
int opens; /* open count */
SANE_String tmpfname; /* temporary file name */
int tfd; /* temp file descriptor */
int rpipe[2]; /* reader pipe descriptors */
int orig_rpipe_flags; /* initial reader pipe flags */
pid_t child; /* child reader process pid */
SnapScan_Mode mode; /* mode */
SnapScan_Mode preview_mode; /* preview mode */
SnapScan_Source source; /* scanning source */
SnapScan_State state; /* scanner state */
u_char cmd[MAX_SCSI_CMD_LEN]; /* scsi command buffer */
u_char *buf; /* data buffer */
size_t phys_buf_sz; /* physical buffer size */
size_t buf_sz; /* effective buffer size */
size_t expected_read_bytes; /* expected amount of data in a single read */
size_t read_bytes; /* amount of actual data read */
size_t bytes_remaining; /* remaining bytes expected from scanner */
size_t actual_res; /* actual resolution */
size_t lines; /* number of scan lines */
size_t bytes_per_line; /* bytes per scan line */
size_t pixels_per_line; /* pixels per scan line */
u_char hconfig; /* hardware configuration byte */
float ms_per_line; /* speed: milliseconds per scan line */
SANE_Bool nonblocking; /* wait on reads for data? */
char *sense_str; /* sense string */
char *as_str; /* additional sense string */
u_char asi1; /* first additional sense info byte */
u_char asi2; /* second additional sense info byte */
SANE_Byte chroma_offset[3]; /* chroma offsets */
SANE_Int chroma;
Source *psrc; /* data source */
SANE_Option_Descriptor
options[NUM_OPTS]; /* the option descriptors */
options[NUM_OPTS]; /* the option descriptors */
Option_Value val[NUM_OPTS];
/* the options themselves... */
SANE_Int res; /* resolution */
SANE_Bool preview; /* preview mode toggle */
SANE_String mode_s; /* scanning mode */
SANE_String source_s; /* scanning source */
SANE_String preview_mode_s; /* scanning mode for preview */
SANE_Fixed tlx; /* window top left x */
SANE_Fixed tly; /* window top left y */
SANE_Fixed brx; /* window bottom right x */
SANE_Fixed bry; /* window bottom right y */
int bright; /* brightness */
int contrast; /* contrast */
SANE_String predef_window; /* predefined window name */
SANE_Fixed gamma_gs; /* gamma correction value (greyscale) */
SANE_Fixed gamma_r; /* gamma correction value (red) */
SANE_Fixed gamma_g; /* gamma correction value (green) */
SANE_Fixed gamma_b; /* gamma correction value (blue) */
SANE_Int *gamma_tables; /* gamma correction vectors */
SANE_Int *gamma_table_gs; /* gamma correction vector (greyscale) */
SANE_Int *gamma_table_r; /* gamma correction vector (red) */
SANE_Int *gamma_table_g; /* gamma correction vector (green) */
SANE_Int *gamma_table_b; /* gamma correction vector (blue) */
int gamma_length; /* length of gamma vectors */
SANE_Bool halftone; /* halftone toggle */
SANE_String dither_matrix; /* the halftone dither matrix */
SANE_Bool negative; /* swap black and white */
SANE_Int threshold; /* threshold for line art */
SANE_Int rgb_lpr; /* lines per scsi read (RGB) */
SANE_Int gs_lpr; /* lines per scsi read (greyscale) */
SANE_Int res; /* resolution */
SANE_Bool preview; /* preview mode toggle */
SANE_String mode_s; /* scanning mode */
SANE_String source_s; /* scanning source */
SANE_String preview_mode_s; /* scanning mode for preview */
SANE_Fixed tlx; /* window top left x */
SANE_Fixed tly; /* window top left y */
SANE_Fixed brx; /* window bottom right x */
SANE_Fixed bry; /* window bottom right y */
int bright; /* brightness */
int contrast; /* contrast */
SANE_String predef_window; /* predefined window name */
SANE_Fixed gamma_gs; /* gamma correction value (greyscale) */
SANE_Fixed gamma_r; /* gamma correction value (red) */
SANE_Fixed gamma_g; /* gamma correction value (green) */
SANE_Fixed gamma_b; /* gamma correction value (blue) */
SANE_Int *gamma_tables; /* gamma correction vectors */
SANE_Int *gamma_table_gs; /* gamma correction vector (greyscale) */
SANE_Int *gamma_table_r; /* gamma correction vector (red) */
SANE_Int *gamma_table_g; /* gamma correction vector (green) */
SANE_Int *gamma_table_b; /* gamma correction vector (blue) */
int gamma_length; /* length of gamma vectors */
SANE_Bool halftone; /* halftone toggle */
SANE_String dither_matrix; /* the halftone dither matrix */
SANE_Bool negative; /* swap black and white */
SANE_Int threshold; /* threshold for line art */
SANE_Int rgb_lpr; /* lines per scsi read (RGB) */
SANE_Int gs_lpr; /* lines per scsi read (greyscale) */
};
#endif
/*
* $Log$
* Revision 1.4 2001/05/26 12:47:34 hmg
* Updated snapscan backend to version 1.2 (from
* Sebastien Sable <Sebastien.Sable@snv.jussieu.fr>).
* Henning Meier-Geinitz <henning@meier-geinitz.de>
* Revision 1.5 2001/10/09 09:45:21 oliverschwartz
* update snapscan to snapshot 20011008
*
* Revision 1.17 2001/10/08 18:22:02 oliverschwartz
* - Disable quality calibration for Acer Vuego 310F
* - Use sanei_scsi_max_request_size as scanner buffer size
* for SCSI devices
* - Added new devices to snapscan.desc
*
* Revision 1.16 2001/09/28 13:39:16 oliverschwartz
* - Added "Snapscan 300" ID string
* - cleanup
* - more debugging messages in snapscan-sources.c
*
* Revision 1.15 2001/09/18 15:01:07 oliverschwartz
* - Read scanner id string again after firmware upload
* to indentify correct model
* - Make firmware upload work for AGFA scanners
* - Change copyright notice
*
* Revision 1.14 2001/09/17 10:01:08 sable
* Added model AGFA 1236U
*
* Revision 1.13 2001/09/09 20:39:52 oliverschwartz
* add identification for 620ST+
*
* Revision 1.12 2001/09/09 18:06:32 oliverschwartz
* add changes from Acer (new models; automatic firmware upload for USB scanners); fix distorted colour scans after greyscale scans (call set_window only in sane_start); code cleanup
*
* Revision 1.11 2001/04/10 12:38:21 sable
* Adding e20 support thanks to Steffen Hübner