1/* sane - Scanner Access Now Easy.
2
3   Copyright (C) 1997, 1998, 2002, 2013 Franck Schnefra, Michel Roelofs,
4   Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller,
5   Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Max Ushakov,
6   Andrew Goodbody, Oliver Schwartz and Kevin Charter
7
8   This file is part of the SANE package.
9
10   This program is free software; you can redistribute it and/or
11   modify it under the terms of the GNU General Public License as
12   published by the Free Software Foundation; either version 2 of the
13   License, or (at your option) any later version.
14
15   This program is distributed in the hope that it will be useful, but
16   WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18   General Public License for more details.
19
20   You should have received a copy of the GNU General Public License
21   along with this program.  If not, see <https://www.gnu.org/licenses/>.
22
23   As a special exception, the authors of SANE give permission for
24   additional uses of the libraries contained in this release of SANE.
25
26   The exception is that, if you link a SANE library with other files
27   to produce an executable, this does not by itself cause the
28   resulting executable to be covered by the GNU General Public
29   License.  Your use of that executable is in no way restricted on
30   account of linking the SANE library code into it.
31
32   This exception does not, however, invalidate any other reasons why
33   the executable file might be covered by the GNU General Public
34   License.
35
36   If you submit changes to SANE to the maintainers to be included in
37   a subsequent release, you agree by submitting the changes that
38   those changes may be distributed with this exception intact.
39
40   If you write modifications of your own for SANE, it is your choice
41   whether to permit this exception to apply to your modifications.
42   If you do not wish that, delete this exception notice.
43
44   This file is a component of the implementation of a backend for many
45   of the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners.
46*/
47
48/*
49   SnapScan backend data sources (implementation)
50*/
51
52/**************************************************************************************
53If you get confused from all the structs (like I did when I first saw them),
54think of it as "C++ in C". If you're accustomed to OO and UML maybe the
55following diagram helps you to make sense of it:
56
57                       ------------------------
58                       !        Source        !
59                       ------------------------
60                       !pss: SnapScan_Scanner*!
61                       ------------------------   +psub
62                       !init() = 0            !-----------------
63                       !remaining() = 0       !                !
64                       !bytesPerLine()        !                !
65                       !pixelsPerLine()       !                !
66                       !get() = 0             !                !{TransformerSource forwards
67                       !done() = 0            !                ! function calls to corres-
68                       ------------------------                ! ponding functions in psub}
69                                   ^                           !
70                                  /_\                          !
71                                   !                           !
72       --------------------------------------------------     /\
73       !               !                !               !     \/
74-------------    -------------    -------------    -------------------
75!SCSISource !    ! FDSource  !    !BufSource  !    !TransformerSource!
76=============    =============    =============    ===================
77!remaining()!    !remaining()!    !remaining()!    !init()           !
78!get()      !    !get()      !    !get()      !    !remaining()      !
79!done()     !    !done()     !    !done()     !    !bytesPerLine()   !
80!init()     !    !init()     !    !init()     !    !pixelsPerLine()  !
81-------------    -------------    -------------    !get()            !
82                                                   !done()           !
83                                                   -------------------
84                                                            ^
85                                                           /_\
86                                                            !
87                                       ------------------------------------
88                                       !                 !                !
89                              ----------------    -------------    -------------
90                              !   Expander   !    ! RGBRouter !    !  Inverter !
91                              ================    =============    =============
92                              !remaining()   !    !remaining()!    !remaining()!
93                              !bytesPerLine()!    !get()      !    !get()      !
94                              !get()         !    !done()     !    !done()     !
95                              !done()        !    !init()     !    !init()     !
96                              !init()        !    -------------    -------------
97                              ----------------
98All instances of the descendants of TransformerSource can be chained together. For
99color scanning, a typical source chain would consist of an RGBRouter sitting on top
100of a SCSISource. In the get() method, RGBRouter will then call the get() method of
101the subsource, process the data and return it.
102
103I hope this makes sense to you (and I got the right idea of the original author's
104intention).
105***********************************************************************************/
106
107static SANE_Status Source_init (Source *pself,
108                                SnapScan_Scanner *pss,
109                                SourceRemaining remaining,
110                                SourceBytesPerLine bytesPerLine,
111                                SourcePixelsPerLine pixelsPerLine,
112                                SourceGet get,
113                                SourceDone done)
114{
115    pself->pss = pss;
116    pself->remaining = remaining;
117    pself->bytesPerLine = bytesPerLine;
118    pself->pixelsPerLine = pixelsPerLine;
119    pself->get = get;
120    pself->done = done;
121    return SANE_STATUS_GOOD;
122}
123
124/* these are defaults, normally used only by base sources */
125
126static SANE_Int Source_bytesPerLine (Source *pself)
127{
128    return pself->pss->bytes_per_line;
129}
130
131static SANE_Int Source_pixelsPerLine (Source *pself)
132{
133    return pself->pss->pixels_per_line;
134}
135
136/**********************************************************************/
137
138/* the base sources */
139typedef enum
140{
141    SCSI_SRC,
142    FD_SRC,
143    BUF_SRC
144} BaseSourceType;
145
146
147typedef struct
148{
149    SOURCE_GUTS;
150    SANE_Int scsi_buf_pos;    /* current position in scsi buffer */
151    SANE_Int scsi_buf_max;    /* data limit */
152    SANE_Int absolute_max;    /* largest possible data read */
153} SCSISource;
154
155static SANE_Int SCSISource_remaining (Source *pself)
156{
157    SCSISource *ps = (SCSISource *) pself;
158    return ps->pss->bytes_remaining + (ps->scsi_buf_max - ps->scsi_buf_pos);
159}
160
161static SANE_Status SCSISource_get (Source *pself,
162                                   SANE_Byte *pbuf,
163                                   SANE_Int *plen)
164{
165    SCSISource *ps = (SCSISource *) pself;
166    SANE_Status status = SANE_STATUS_GOOD;
167    SANE_Int remaining = *plen;
168    char* me = "SCSISource_get";
169
170    DBG (DL_CALL_TRACE, "%s\n", me);
171    while (remaining > 0
172           && pself->remaining(pself) > 0
173           && status == SANE_STATUS_GOOD
174           && !cancelRead)
175    {
176        SANE_Int ndata = ps->scsi_buf_max - ps->scsi_buf_pos;
177        DBG (DL_DATA_TRACE, "%s: ndata %d; remaining %d\n", me, ndata, remaining);
178        if (ndata == 0)
179        {
180            ps->pss->expected_read_bytes = MIN((size_t)ps->absolute_max,
181                                           ps->pss->bytes_remaining);
182            ps->scsi_buf_pos = 0;
183            ps->scsi_buf_max = 0;
184            status = scsi_read (ps->pss, READ_IMAGE);
185            if (status != SANE_STATUS_GOOD)
186                break;
187            ps->scsi_buf_max = ps->pss->read_bytes;
188            ndata = ps->pss->read_bytes;
189            ps->pss->bytes_remaining -= ps->pss->read_bytes;
190            DBG (DL_DATA_TRACE, "%s: pos: %d; max: %d; expected: %lu; read: %lu\n",
191                me, ps->scsi_buf_pos, ps->scsi_buf_max, (u_long) ps->pss->expected_read_bytes,
192                (u_long) ps->pss->read_bytes);
193        }
194        ndata = MIN(ndata, remaining);
195        memcpy (pbuf, ps->pss->buf + ps->scsi_buf_pos, (size_t)ndata);
196        pbuf += ndata;
197        ps->scsi_buf_pos += ndata;
198        remaining -= ndata;
199    }
200    *plen -= remaining;
201    return status;
202}
203
204static SANE_Status SCSISource_done (Source *pself)
205{
206    DBG(DL_MINOR_INFO, "SCSISource_done\n");
207    UNREFERENCED_PARAMETER(pself);
208    return SANE_STATUS_GOOD;
209}
210
211static SANE_Status SCSISource_init (SCSISource *pself, SnapScan_Scanner *pss)
212{
213    SANE_Status status = Source_init ((Source *) pself, pss,
214                                      SCSISource_remaining,
215                                      Source_bytesPerLine,
216                                      Source_pixelsPerLine,
217                                      SCSISource_get,
218                                      SCSISource_done);
219    if (status == SANE_STATUS_GOOD)
220    {
221        pself->scsi_buf_max = 0;
222        pself->scsi_buf_pos = 0;
223        pself->absolute_max =
224            (pss->phys_buf_sz/pss->bytes_per_line)*pss->bytes_per_line;
225    }
226    return status;
227}
228
229/* File sources */
230
231typedef struct
232{
233    SOURCE_GUTS;
234    int fd;
235    SANE_Int bytes_remaining;
236} FDSource;
237
238static SANE_Int FDSource_remaining (Source *pself)
239{
240    FDSource *ps = (FDSource *) pself;
241    return ps->bytes_remaining;
242}
243
244static SANE_Status FDSource_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen)
245{
246    SANE_Status status = SANE_STATUS_GOOD;
247    FDSource *ps = (FDSource *) pself;
248    SANE_Int remaining = *plen;
249
250    while (remaining > 0
251           && pself->remaining(pself) > 0
252           && status == SANE_STATUS_GOOD)
253    {
254        SANE_Int bytes_read = read (ps->fd, pbuf, remaining);
255        if (bytes_read == -1)
256        {
257            if (errno == EAGAIN)
258            {
259                /* No data currently available */
260                break;
261            }
262            /* It's an IO error */
263            DBG (DL_MAJOR_ERROR, "%s: read failed: %s\n",
264                     __func__, strerror(errno));
265            status = SANE_STATUS_IO_ERROR;
266        }
267        else if (bytes_read == 0)
268        {
269            /* EOF of current reading */
270            DBG(DL_DATA_TRACE, "%s: EOF\n",__func__);
271            break;
272        }
273        ps->bytes_remaining -= bytes_read;
274        remaining -= bytes_read;
275        pbuf += bytes_read;
276    }
277    *plen -= remaining;
278    return status;
279}
280
281static SANE_Status FDSource_done (Source *pself)
282{
283    close(((FDSource *) pself)->fd);
284    return SANE_STATUS_GOOD;
285}
286
287static SANE_Status FDSource_init (FDSource *pself,
288                                  SnapScan_Scanner *pss,
289                                  int fd)
290{
291    SANE_Status status = Source_init ((Source *) pself,
292                                      pss,
293                                      FDSource_remaining,
294                                      Source_bytesPerLine,
295                                      Source_pixelsPerLine,
296                                      FDSource_get,
297                                      FDSource_done);
298    if (status == SANE_STATUS_GOOD)
299    {
300        pself->fd = fd;
301        pself->bytes_remaining = pss->bytes_per_line * (pss->lines + pss->chroma);
302    }
303    return status;
304}
305
306
307/* buffer sources simply read from a pre-filled buffer; we have these
308   so that we can include source chain processing overhead in the
309   measure_transfer_rate() function */
310
311typedef struct
312{
313    SOURCE_GUTS;
314    SANE_Byte *buf;
315    SANE_Int buf_size;
316    SANE_Int buf_pos;
317} BufSource;
318
319static SANE_Int BufSource_remaining (Source *pself)
320{
321    BufSource *ps = (BufSource *) pself;
322    return  ps->buf_size - ps->buf_pos;
323}
324
325static SANE_Status BufSource_get (Source *pself,
326                                  SANE_Byte *pbuf,
327                                  SANE_Int *plen)
328{
329    BufSource *ps = (BufSource *) pself;
330    SANE_Status status = SANE_STATUS_GOOD;
331    SANE_Int to_move = MIN(*plen, pself->remaining(pself));
332    if (to_move == 0)
333    {
334        status = SANE_STATUS_EOF;
335    }
336    else
337    {
338        memcpy (pbuf, ps->buf + ps->buf_pos, to_move);
339        ps->buf_pos += to_move;
340        *plen = to_move;
341    }
342    return status;
343}
344
345static SANE_Status BufSource_done (Source *pself)
346{
347    UNREFERENCED_PARAMETER(pself);
348    return SANE_STATUS_GOOD;
349}
350
351static SANE_Status BufSource_init (BufSource *pself,
352                                   SnapScan_Scanner *pss,
353                                     SANE_Byte *buf,
354                                   SANE_Int buf_size)
355{
356    SANE_Status status = Source_init ((Source *) pself,
357                                      pss,
358                                      BufSource_remaining,
359                                      Source_bytesPerLine,
360                                      Source_pixelsPerLine,
361                                      BufSource_get,
362                                      BufSource_done);
363    DBG(DL_DATA_TRACE, "BufSource_init: buf_size=%d\n", buf_size);
364    if (status == SANE_STATUS_GOOD)
365    {
366        pself->buf = buf;
367        pself->buf_size = buf_size;
368        pself->buf_pos = 0;
369    }
370    return status;
371}
372
373/* base source creation */
374
375static SANE_Status create_base_source (SnapScan_Scanner *pss,
376                                       BaseSourceType st,
377                                       Source **pps)
378{
379    SANE_Status status = SANE_STATUS_GOOD;
380    *pps = NULL;
381    switch (st)
382    {
383    case SCSI_SRC:
384        *pps = (Source *) malloc(sizeof(SCSISource));
385        if (*pps == NULL)
386        {
387            DBG (DL_MAJOR_ERROR, "failed to allocate SCSISource");
388            status = SANE_STATUS_NO_MEM;
389        }
390        else
391        {
392            status = SCSISource_init ((SCSISource *) *pps, pss);
393        }
394    break;
395    case FD_SRC:
396        *pps = (Source *) malloc(sizeof(FDSource));
397        if (*pps == NULL)
398        {
399            DBG (DL_MAJOR_ERROR, "failed to allocate FDSource");
400            status = SANE_STATUS_NO_MEM;
401        }
402        else
403        {
404            status = FDSource_init ((FDSource *) *pps, pss, pss->rpipe[0]);
405        }
406    break;
407    case BUF_SRC:
408        *pps = (Source *) malloc(sizeof(BufSource));
409        if (*pps == NULL)
410        {
411            DBG (DL_MAJOR_ERROR, "failed to allocate BufSource");
412            status = SANE_STATUS_NO_MEM;
413        }
414        else
415        {
416            status = BufSource_init ((BufSource *) *pps,
417                                     pss,
418                                     pss->buf,
419                                     pss->read_bytes);
420        }
421    break;
422    default:
423        DBG (DL_MAJOR_ERROR, "illegal base source type %d", st);
424        break;
425    }
426    return status;
427}
428
429/**********************************************************************/
430
431/* The transformer sources */
432
433#define TX_SOURCE_GUTS \
434        SOURCE_GUTS;\
435        Source *psub    /* sub-source */
436
437typedef struct
438{
439    TX_SOURCE_GUTS;
440} TxSource;
441
442static SANE_Int TxSource_remaining (Source *pself)
443{
444    TxSource *ps = (TxSource *) pself;
445    return ps->psub->remaining(ps->psub);
446}
447
448static SANE_Int TxSource_bytesPerLine (Source *pself)
449{
450    TxSource *ps = (TxSource *) pself;
451    return ps->psub->bytesPerLine(ps->psub);
452}
453
454static SANE_Int TxSource_pixelsPerLine (Source *pself)
455{
456    TxSource *ps = (TxSource *) pself;
457    return ps->psub->pixelsPerLine(ps->psub);
458}
459
460static SANE_Status TxSource_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen)
461{
462    TxSource *ps = (TxSource *) pself;
463    return ps->psub->get(ps->psub, pbuf, plen);
464}
465
466static SANE_Status TxSource_done (Source *pself)
467{
468    TxSource *ps = (TxSource *) pself;
469    SANE_Status status = ps->psub->done(ps->psub);
470    free(ps->psub);
471    ps->psub = NULL;
472    return status;
473}
474
475static SANE_Status TxSource_init (TxSource *pself,
476                                  SnapScan_Scanner *pss,
477                                  SourceRemaining remaining,
478                                  SourceBytesPerLine bytesPerLine,
479                                  SourcePixelsPerLine pixelsPerLine,
480                                  SourceGet get,
481                                  SourceDone done,
482                                  Source *psub)
483{
484    SANE_Status status = Source_init((Source *) pself,
485                                     pss,
486                                     remaining,
487                                     bytesPerLine,
488                                     pixelsPerLine,
489                                     get,
490                                     done);
491    if (status == SANE_STATUS_GOOD)
492        pself->psub = psub;
493    return status;
494}
495
496/* The expander makes three-channel, one-bit, raw scanner data into
497   8-bit data. It is used to support the bilevel colour scanning mode */
498
499typedef struct
500{
501    TX_SOURCE_GUTS;
502    SANE_Byte *ch_buf;            /* channel buffer */
503    SANE_Int   ch_size;            /* channel buffer size = #bytes in a channel */
504    SANE_Int   ch_ndata;        /* actual #bytes in channel buffer */
505    SANE_Int   ch_pos;            /* position in buffer */
506    SANE_Int   bit;                /* current bit */
507    SANE_Int   last_bit;        /* current last bit (counting down) */
508    SANE_Int   last_last_bit;    /* last bit in the last byte of the channel */
509} Expander;
510
511static SANE_Int Expander_remaining (Source *pself)
512{
513    Expander *ps = (Expander *) pself;
514    SANE_Int sub_remaining = TxSource_remaining(pself);
515    SANE_Int sub_bits_per_channel = TxSource_pixelsPerLine(pself);
516    SANE_Int whole_channels = sub_remaining/ps->ch_size;
517    SANE_Int result = whole_channels*sub_bits_per_channel;
518
519    if (ps->ch_pos < ps->ch_size)
520    {
521        SANE_Int bits_covered = MAX((ps->ch_pos - 1)*8, 0) + 7 - ps->bit;
522        result += sub_bits_per_channel - bits_covered;
523    }
524
525    return result;
526}
527
528static SANE_Int Expander_bytesPerLine (Source *pself)
529{
530    return TxSource_pixelsPerLine(pself)*3;
531}
532
533static SANE_Status Expander_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen)
534{
535    Expander *ps = (Expander *) pself;
536    SANE_Status status = SANE_STATUS_GOOD;
537    SANE_Int remaining = *plen;
538
539    while (remaining > 0
540           &&
541           pself->remaining(pself) > 0 &&
542           !cancelRead)
543    {
544        if (ps->ch_pos == ps->ch_ndata)
545        {
546            /* we need more data; try to get the remainder of the current
547               channel, or else the next channel */
548            SANE_Int ndata = ps->ch_size - ps->ch_ndata;
549            if (ndata == 0)
550            {
551                ps->ch_ndata = 0;
552                ps->ch_pos = 0;
553                ndata = ps->ch_size;
554            }
555            status = TxSource_get(pself, ps->ch_buf + ps->ch_pos, &ndata);
556            if (status != SANE_STATUS_GOOD)
557                break;
558            if (ndata == 0)
559                break;
560            ps->ch_ndata += ndata;
561            if (ps->ch_pos == (ps->ch_size - 1))
562                ps->last_bit = ps->last_last_bit;
563            else
564                ps->last_bit = 0;
565            ps->bit = 7;
566        }
567        *pbuf = ((ps->ch_buf[ps->ch_pos] >> ps->bit) & 0x01) ? 0xFF : 0x00;
568        pbuf++;
569        remaining--;
570
571        if (ps->bit == ps->last_bit)
572        {
573            ps->bit = 7;
574            ps->ch_pos++;
575            if (ps->ch_pos == (ps->ch_size - 1))
576                ps->last_bit = ps->last_last_bit;
577            else
578                ps->last_bit = 0;
579        }
580        else
581        {
582            ps->bit--;
583        }
584    }
585
586    *plen -= remaining;
587    return status;
588}
589
590static SANE_Status Expander_done (Source *pself)
591{
592    Expander *ps = (Expander *) pself;
593    SANE_Status status = TxSource_done(pself);
594    free(ps->ch_buf);
595    ps->ch_buf = NULL;
596    ps->ch_size = 0;
597    ps->ch_pos = 0;
598    return status;
599}
600
601static SANE_Status Expander_init (Expander *pself,
602                  SnapScan_Scanner *pss,
603                                  Source *psub)
604{
605    SANE_Status status = TxSource_init((TxSource *) pself,
606                                       pss,
607                                       Expander_remaining,
608                                       Expander_bytesPerLine,
609                                       TxSource_pixelsPerLine,
610                                       Expander_get,
611                                       Expander_done,
612                                       psub);
613    if (status == SANE_STATUS_GOOD)
614    {
615        pself->ch_size = TxSource_bytesPerLine((Source *) pself)/3;
616        pself->ch_buf = (SANE_Byte *) malloc(pself->ch_size);
617        if (pself->ch_buf == NULL)
618        {
619            DBG (DL_MAJOR_ERROR,
620                 "%s: couldn't allocate channel buffer.\n",
621                 __func__);
622            status = SANE_STATUS_NO_MEM;
623        }
624        else
625        {
626            pself->ch_ndata = 0;
627            pself->ch_pos = 0;
628            pself->last_last_bit = pself->pixelsPerLine((Source *) pself)%8;
629            if (pself->last_last_bit == 0)
630                pself->last_last_bit = 7;
631            pself->last_last_bit = 7 - pself->last_last_bit;
632            pself->bit = 7;
633            if (pself->ch_size > 1)
634                pself->last_bit = 0;
635            else
636                pself->last_bit = pself->last_last_bit;
637        }
638    }
639    return status;
640}
641
642static SANE_Status create_Expander (SnapScan_Scanner *pss,
643                                    Source *psub,
644                                    Source **pps)
645{
646    SANE_Status status = SANE_STATUS_GOOD;
647    *pps = (Source *) malloc(sizeof(Expander));
648    if (*pps == NULL)
649    {
650        DBG (DL_MAJOR_ERROR,
651             "%s: failed to allocate Expander.\n",
652             __func__);
653        status = SANE_STATUS_NO_MEM;
654    }
655    else
656    {
657        status = Expander_init ((Expander *) *pps, pss, psub);
658    }
659    return status;
660}
661
662/*
663   This filter implements a fix for scanners that have some columns
664   of pixels offset. Currently it only shifts every other column
665   starting with the first one down ch_offset pixels.
666
667   The Deinterlacer detects if data is in SANE RGB frame format (3 bytes/pixel)
668   or in Grayscale (1 byte/pixel).
669
670   The first ch_offset lines of data in the output are fudged so that even indexed
671   add odd indexed pixels will have the same value. This is necessary because
672   the real pixel values of the columns that are shifted down are not
673   in the data for the first ch_offset lines. A better way to handle this would be to
674   scan in ch_offset extra lines of data, but I haven't figured out how to do this
675   yet.
676
677*/
678
679typedef struct
680{
681    TX_SOURCE_GUTS;
682    SANE_Byte *ch_buf;            /* channel buffer */
683    SANE_Int   ch_size;           /* channel buffer size */
684    SANE_Int   ch_line_size;      /* size of one line */
685    SANE_Int   ch_ndata;          /* actual #bytes in channel buffer */
686    SANE_Int   ch_pos;            /* position in buffer */
687    SANE_Int   ch_bytes_per_pixel;
688    SANE_Bool  ch_lineart;
689    SANE_Int   ch_offset;         /* The number of lines to be shifted */
690    SANE_Bool  ch_past_init;      /* flag indicating if we have enough data to shift pixels down */
691    SANE_Bool  ch_shift_even;     /* flag indicating whether even or odd pixels are shifted */
692} Deinterlacer;
693
694static SANE_Int Deinterlacer_remaining (Source *pself)
695{
696    Deinterlacer *ps = (Deinterlacer *) pself;
697    SANE_Int result = TxSource_remaining(pself);
698    result += ps->ch_ndata - ps->ch_pos;
699    return result;
700}
701
702static SANE_Status Deinterlacer_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen)
703{
704    Deinterlacer *ps = (Deinterlacer *) pself;
705    SANE_Status status = SANE_STATUS_GOOD;
706    SANE_Int remaining = *plen;
707    SANE_Int org_len = *plen;
708    char *me = "Deinterlacer_get";
709
710    DBG(DL_DATA_TRACE, "%s: remaining=%d, pself->remaining=%d, ch_ndata=%d, ch_pos=%d\n",
711            me, remaining, pself->remaining(pself), ps->ch_ndata, ps->ch_pos);
712
713    while (remaining > 0
714           &&
715           pself->remaining(pself) > 0 &&
716           !cancelRead)
717    {
718        if (ps->ch_pos % (ps->ch_line_size) == ps->ch_ndata % (ps->ch_line_size) )
719        {
720            /* we need more data; try to get the remainder of the current
721               line, or else the next line */
722            SANE_Int ndata = (ps->ch_line_size) - ps->ch_ndata % (ps->ch_line_size);
723            if (ps->ch_pos >= ps->ch_size)
724            {
725	        /* wrap to the beginning of the buffer if we need to */
726                ps->ch_ndata = 0;
727                ps->ch_pos = 0;
728                ndata = ps->ch_line_size;
729            }
730            status = TxSource_get(pself, ps->ch_buf + ps->ch_pos, &ndata);
731            if (status != SANE_STATUS_GOOD)
732                break;
733            if (ndata == 0)
734                break;
735            ps->ch_ndata += ndata;
736        }
737        /* Handle special lineart mode: Valid pixels need to be masked */
738        if (ps->ch_lineart)
739        {
740            if (ps->ch_past_init)
741            {
742                if (ps->ch_shift_even)
743                {
744                    /* Even columns need to be shifted, i.e. bits 1,3,5,7 -> 0xaa */
745                    /* use valid pixels from this line and shifted pixels from ch_size lines back */
746                    *pbuf = (ps->ch_buf[ps->ch_pos] & 0x55) |
747                            (ps->ch_buf[(ps->ch_pos + (ps->ch_line_size)) % ps->ch_size] & 0xaa);
748                }
749                else
750                {
751                    /* Odd columns need to be shifted, i.e. bits 0,2,4,6 -> 0x55 */
752                    *pbuf = (ps->ch_buf[ps->ch_pos] & 0xaa) |
753                            (ps->ch_buf[(ps->ch_pos + (ps->ch_line_size)) % ps->ch_size] & 0x55);
754                }
755            }
756            else
757            {
758                /* not enough data. duplicate pixel values from previous column */
759                if (ps->ch_shift_even)
760                {
761                    /* bits 0,2,4,6 contain valid data -> 0x55 */
762                    SANE_Byte valid_pixel = ps->ch_buf[ps->ch_pos] & 0x55;
763                    *pbuf = valid_pixel | (valid_pixel >> 1);
764                }
765                else
766                {
767
768                    /* bits 1,3,5,7 contain valid data -> 0xaa */
769                    SANE_Byte valid_pixel = ps->ch_buf[ps->ch_pos] & 0xaa;
770                    *pbuf = valid_pixel | (valid_pixel << 1);
771                }
772            }
773        }
774        else /* colour / grayscale mode */
775        {
776            if ((ps->ch_shift_even && ((ps->ch_pos/ps->ch_bytes_per_pixel) % 2 == 0)) ||
777                (!ps->ch_shift_even && ((ps->ch_pos/ps->ch_bytes_per_pixel) % 2 == 1)))
778            {
779                /* the even indexed pixels need to be shifted down */
780                if (ps->ch_past_init){
781                    /* We need to use data 4 lines back */
782                    /* So we just go one forward and it will wrap around to 4 back. */
783                    *pbuf = ps->ch_buf[(ps->ch_pos + (ps->ch_line_size)) % ps->ch_size];
784                }else{
785                    /* Use data from the next pixel for even indexed pixels
786                      if we are on the first few lines.
787                      TODO: also we will overread the buffer if the buffer read ended
788                      on the first pixel. */
789                    if (ps->ch_pos % (ps->ch_line_size) == 0 )
790                        *pbuf = ps->ch_buf[ps->ch_pos+ps->ch_bytes_per_pixel];
791                    else
792                        *pbuf = ps->ch_buf[ps->ch_pos-ps->ch_bytes_per_pixel];
793                }
794            }else{
795                /* odd indexed pixels are okay */
796                *pbuf = ps->ch_buf[ps->ch_pos];
797            }
798        }
799	/* set the flag so we know we have enough data to start shifting columns */
800	if (ps->ch_pos >= ps->ch_line_size * ps->ch_offset)
801	   ps->ch_past_init = SANE_TRUE;
802
803        pbuf++;
804        remaining--;
805        ps->ch_pos++;
806    }
807
808    *plen -= remaining;
809
810    DBG(DL_DATA_TRACE,
811        "%s: Request=%d, remaining=%d, read=%d, TXSource_rem=%d, bytes_rem=%lu\n",
812        me,
813        org_len,
814        pself->remaining(pself),
815        *plen,
816        TxSource_remaining(pself),
817        (u_long) ps->pss->bytes_remaining);
818    return status;
819}
820
821static SANE_Status Deinterlacer_done (Source *pself)
822{
823    Deinterlacer *ps = (Deinterlacer *) pself;
824    SANE_Status status = TxSource_done(pself);
825    free(ps->ch_buf);
826    ps->ch_buf = NULL;
827    ps->ch_size = 0;
828    ps->ch_line_size = 0;
829    ps->ch_pos = 0;
830    return status;
831}
832
833static SANE_Status Deinterlacer_init (Deinterlacer *pself,
834                  SnapScan_Scanner *pss,
835                                  Source *psub)
836{
837    SANE_Status status = TxSource_init((TxSource *) pself,
838                                       pss,
839                                       Deinterlacer_remaining,
840                                       TxSource_bytesPerLine,
841                                       TxSource_pixelsPerLine,
842                                       Deinterlacer_get,
843                                       Deinterlacer_done,
844                                       psub);
845    if (status == SANE_STATUS_GOOD)
846    {
847        pself->ch_shift_even = SANE_TRUE;
848        switch (pss->pdev->model)
849        {
850        case PERFECTION3490:
851            pself->ch_offset = 8;
852            if ((actual_mode(pss) == MD_GREYSCALE) || (actual_mode(pss) == MD_LINEART))
853                 pself->ch_shift_even = SANE_FALSE;
854            break;
855        case PERFECTION2480:
856        default:
857            pself->ch_offset = 4;
858            break;
859        }
860        pself->ch_line_size = TxSource_bytesPerLine((Source *) pself);
861        /* We need at least ch_offset+1 lines of buffer in order
862           to shift up ch_offset pixels. */
863        pself->ch_size = pself->ch_line_size * (pself->ch_offset + 1);
864        pself->ch_buf = (SANE_Byte *) malloc(pself->ch_size);
865        if (pself->ch_buf == NULL)
866        {
867            DBG (DL_MAJOR_ERROR,
868                 "%s: couldn't allocate channel buffer.\n",
869                 __func__);
870            status = SANE_STATUS_NO_MEM;
871        }
872        else
873        {
874            pself->ch_ndata = 0;
875            pself->ch_pos = 0;
876            pself->ch_past_init = SANE_FALSE;
877	    if ((actual_mode(pss) == MD_GREYSCALE) || (actual_mode(pss) == MD_LINEART))
878	    	pself->ch_bytes_per_pixel = 1;
879	    else
880	    	pself->ch_bytes_per_pixel = 3;
881	    if (pss->bpp_scan == 16)
882		pself->ch_bytes_per_pixel *= 2;
883        }
884        pself->ch_lineart = (actual_mode(pss) == MD_LINEART);
885    }
886    return status;
887}
888
889static SANE_Status create_Deinterlacer (SnapScan_Scanner *pss,
890                                    Source *psub,
891                                    Source **pps)
892{
893    SANE_Status status = SANE_STATUS_GOOD;
894    *pps = (Source *) malloc(sizeof(Deinterlacer));
895    if (*pps == NULL)
896    {
897        DBG (DL_MAJOR_ERROR,
898             "%s: failed to allocate Deinterlacer.\n",
899             __func__);
900        status = SANE_STATUS_NO_MEM;
901    }
902    else
903    {
904        status = Deinterlacer_init ((Deinterlacer *) *pps, pss, psub);
905    }
906    return status;
907}
908
909/* ----------------------------------------------------- */
910
911/* the RGB router assumes 8-bit RGB data arranged in contiguous
912   channels, possibly with R-G and R-B offsets, and rearranges the
913   data into SANE RGB frame format */
914
915typedef struct
916{
917    TX_SOURCE_GUTS;
918    SANE_Byte *cbuf;            /* circular line buffer */
919    SANE_Byte *xbuf;            /* single line buffer */
920    SANE_Int pos;                    /* current position in xbuf */
921    SANE_Int cb_size;            /* size of the circular buffer */
922    SANE_Int cb_line_size;/* size of a line in the circular buffer */
923    SANE_Int cb_start;        /* start of valid data in the circular buffer */
924    SANE_Int cb_finish;        /* finish of valid data, for next read */
925    SANE_Int ch_offset[3];/* offset in cbuf */
926    SANE_Int round_req;
927    SANE_Int round_read;
928} RGBRouter;
929
930static void put_int16r (int n, u_char *p)
931{
932	p[0] = (n & 0x00ff);
933	p[1] = (n & 0xff00) >> 8;
934}
935
936
937static SANE_Int RGBRouter_remaining (Source *pself)
938{
939    RGBRouter *ps = (RGBRouter *) pself;
940   SANE_Int remaining;
941    if (ps->round_req == ps->cb_size)
942        remaining = TxSource_remaining(pself) - ps->cb_size + ps->cb_line_size;
943    else
944      remaining = TxSource_remaining(pself) + ps->cb_line_size - ps->pos;
945   return (remaining);
946}
947
948static SANE_Status RGBRouter_get (Source *pself,
949                                  SANE_Byte *pbuf,
950                                  SANE_Int *plen)
951{
952    RGBRouter *ps = (RGBRouter *) pself;
953    SANE_Status status = SANE_STATUS_GOOD;
954    SANE_Int remaining = *plen;
955    SANE_Byte *s;
956    SANE_Int i, t;
957    SANE_Int r, g, b;
958    SANE_Int run_req;
959    SANE_Int org_len = *plen;
960    char *me = "RGBRouter_get";
961
962    while (remaining > 0  &&  pself->remaining(pself) > 0 && !cancelRead)
963    {
964        DBG(DL_DATA_TRACE, "%s: remaining=%d, pself->remaining=%d, round_req=%d, cb_size=%d\n",
965            me, remaining, pself->remaining(pself), ps->round_req, ps->cb_size);
966        /* Check if there is no valid data left from previous get */
967        if (ps->pos >= ps->cb_line_size)
968        {
969            /* Try to get more data. either one line or
970               full buffer (first time) */
971            do
972            {
973                run_req = ps->round_req - ps->round_read;
974                status = TxSource_get (pself,
975                                       ps->cbuf + ps->cb_start + ps->round_read,
976                                       &run_req);
977                if (status != SANE_STATUS_GOOD || run_req==0)
978                {
979                    *plen -= remaining;
980                    if ( *plen > 0 )
981                        DBG(DL_DATA_TRACE, "%s: request=%d, read=%d\n",
982                            me, org_len, *plen);
983                    return status;
984                }
985                ps->round_read += run_req;
986            }
987            while ((ps->round_req > ps->round_read) && !cancelRead);
988
989            /* route RGB */
990            ps->cb_start = (ps->cb_start + ps->round_read)%ps->cb_size;
991            s = ps->xbuf;
992            r = (ps->cb_start + ps->ch_offset[0])%ps->cb_size;
993            g = (ps->cb_start + ps->ch_offset[1])%ps->cb_size;
994            b = (ps->cb_start + ps->ch_offset[2])%ps->cb_size;
995            for (i = 0;  i < ps->cb_line_size/3;  i++)
996            {
997                if (pself->pss->bpp_scan == 8)
998                {
999                    *s++ = ps->cbuf[r++];
1000                    *s++ = ps->cbuf[g++];
1001                    *s++ = ps->cbuf[b++];
1002                }
1003                else if (pself->pss->pdev->model == SCANWIT2720S)
1004                {
1005                    t = (((ps->cbuf[r+1] << 8) | ps->cbuf[r]) & 0xfff) << 4;
1006                    put_int16r (t, s);
1007                    s += 2;
1008                    r += 2;
1009                    t = (((ps->cbuf[g+1] << 8) | ps->cbuf[g]) & 0xfff) << 4;
1010                    put_int16r (t, s);
1011                    s += 2;
1012                    g += 2;
1013                    t = (((ps->cbuf[b+1] << 8) | ps->cbuf[b]) & 0xfff) << 4;
1014                    put_int16r (t, s);
1015                    s += 2;
1016                    b += 2;
1017                    i++;
1018                }
1019                else
1020                {
1021                    *s++ = ps->cbuf[r++];
1022                    *s++ = ps->cbuf[r++];
1023                    *s++ = ps->cbuf[g++];
1024                    *s++ = ps->cbuf[g++];
1025                    *s++ = ps->cbuf[b++];
1026                    *s++ = ps->cbuf[b++];
1027                    i++;
1028                }
1029            }
1030
1031            /* end of reading & offsetiing whole line data;
1032               reset valid position */
1033            ps->pos = 0;
1034
1035            /* prepare for next round */
1036            ps->round_req = ps->cb_line_size;
1037            ps->round_read =0;
1038        }
1039
1040        /* Repack the whole scan line and copy to caller's buffer */
1041        while (remaining > 0  &&  ps->pos < ps->cb_line_size)
1042        {
1043            *pbuf++ = ps->xbuf[ps->pos++];
1044            remaining--;
1045        }
1046    }
1047    *plen -= remaining;
1048    DBG(DL_DATA_TRACE,
1049        "%s: Request=%d, remaining=%d, read=%d, TXSource_rem=%d, bytes_rem=%lu\n",
1050        me,
1051        org_len,
1052        pself->remaining(pself),
1053        *plen,
1054        TxSource_remaining(pself),
1055        (u_long) ps->pss->bytes_remaining);
1056    return status;
1057}
1058
1059static SANE_Status RGBRouter_done (Source *pself)
1060{
1061    RGBRouter *ps = (RGBRouter *) pself;
1062    SANE_Status status = TxSource_done(pself);
1063
1064    free(ps->cbuf);
1065    free(ps->xbuf);
1066    ps->cbuf = NULL;
1067    ps->cb_start = -1;
1068    ps->pos = 0;
1069    return status;
1070}
1071
1072static SANE_Status RGBRouter_init (RGBRouter *pself,
1073                           SnapScan_Scanner *pss,
1074                                   Source *psub)
1075{
1076    SANE_Status status = TxSource_init((TxSource *) pself,
1077                                       pss,
1078                                       RGBRouter_remaining,
1079                                       TxSource_bytesPerLine,
1080                                       TxSource_pixelsPerLine,
1081                                       RGBRouter_get,
1082                                       RGBRouter_done,
1083                                       psub);
1084    if (status == SANE_STATUS_GOOD)
1085    {
1086        SANE_Int lines_in_buffer = 0;
1087
1088        /* Size the buffer to accommodate the necessary number of scan
1089           lines to cater for the offset between R, G and B */
1090        lines_in_buffer = pss->chroma + 1;
1091        pself->cb_line_size = pself->bytesPerLine((Source *) pself);
1092        pself->cb_size = pself->cb_line_size*lines_in_buffer;
1093        pself->pos = pself->cb_line_size;
1094
1095        pself->round_req = pself->cb_size;
1096        pself->round_read = 0;
1097
1098        pself->cbuf = (SANE_Byte *) malloc(pself->cb_size);
1099        pself->xbuf = (SANE_Byte *) malloc(pself->cb_line_size);
1100        if (pself->cbuf == NULL  ||  pself->xbuf == NULL)
1101        {
1102            DBG (DL_MAJOR_ERROR,
1103                 "%s: failed to allocate circular buffer.\n",
1104                 __func__);
1105            status = SANE_STATUS_NO_MEM;
1106        }
1107        else
1108        {
1109            SANE_Int ch;
1110
1111            pself->cb_start = 0;
1112            for (ch = 0;  ch < 3;  ch++)
1113            {
1114                pself->ch_offset[ch] =
1115                        pss->chroma_offset[ch] * pself->cb_line_size
1116                        + ch * (pself->cb_line_size / 3);
1117            }
1118        }
1119        DBG(DL_MINOR_INFO, "RGBRouter_init: buf_size: %d x %d = %d\n",
1120            pself->cb_line_size, lines_in_buffer, pself->cb_size);
1121        DBG(DL_MINOR_INFO, "RGBRouter_init: buf offset R:%d G:%d B:%d\n",
1122            pself->ch_offset[0], pself->ch_offset[1],pself->ch_offset[2]);
1123    }
1124    return status;
1125}
1126
1127static SANE_Status create_RGBRouter (SnapScan_Scanner *pss,
1128                                     Source *psub,
1129                                     Source **pps)
1130{
1131    static char me[] = "create_RGBRouter";
1132    SANE_Status status = SANE_STATUS_GOOD;
1133
1134    DBG (DL_CALL_TRACE, "%s\n", me);
1135    *pps = (Source *) malloc(sizeof(RGBRouter));
1136    if (*pps == NULL)
1137    {
1138        DBG (DL_MAJOR_ERROR, "%s: failed to allocate RGBRouter.\n",
1139             __func__);
1140        status = SANE_STATUS_NO_MEM;
1141    }
1142    else
1143    {
1144        status = RGBRouter_init ((RGBRouter *) *pps, pss, psub);
1145    }
1146    return status;
1147}
1148
1149/* An Inverter is used to invert the bits in a lineart image */
1150
1151typedef struct
1152{
1153    TX_SOURCE_GUTS;
1154} Inverter;
1155
1156static SANE_Status Inverter_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen)
1157{
1158    SANE_Status status = TxSource_get (pself, pbuf, plen);
1159    if (status == SANE_STATUS_GOOD)
1160    {
1161        int i;
1162        for (i = 0;  i < *plen;  i++)
1163            pbuf[i] ^= 0xFF;
1164    }
1165    return status;
1166}
1167
1168static SANE_Status Inverter_init (Inverter *pself,
1169                                  SnapScan_Scanner *pss,
1170                                  Source *psub)
1171{
1172    return  TxSource_init ((TxSource *) pself,
1173                           pss,
1174                           TxSource_remaining,
1175                           TxSource_bytesPerLine,
1176                           TxSource_pixelsPerLine,
1177                           Inverter_get,
1178                           TxSource_done,
1179                           psub);
1180}
1181
1182static SANE_Status create_Inverter (SnapScan_Scanner *pss,
1183                                    Source *psub,
1184                                    Source **pps)
1185{
1186    SANE_Status status = SANE_STATUS_GOOD;
1187    *pps = (Source *) malloc(sizeof(Inverter));
1188    if (*pps == NULL)
1189    {
1190        DBG (DL_MAJOR_ERROR, "%s: failed to allocate Inverter.\n",
1191                 __func__);
1192        status = SANE_STATUS_NO_MEM;
1193    }
1194    else
1195    {
1196        status = Inverter_init ((Inverter *) *pps, pss, psub);
1197    }
1198    return status;
1199}
1200
1201/* Source chain creation */
1202
1203static SANE_Status create_source_chain (SnapScan_Scanner *pss,
1204                                        BaseSourceType bst,
1205                                        Source **pps)
1206{
1207   static char me[] = "create_source_chain";
1208    SANE_Status status = create_base_source (pss, bst, pps);
1209
1210   DBG (DL_CALL_TRACE, "%s\n", me);
1211    if (status == SANE_STATUS_GOOD)
1212    {
1213        SnapScan_Mode mode = actual_mode(pss);
1214        switch (mode)
1215        {
1216        case MD_COLOUR:
1217            status = create_RGBRouter (pss, *pps, pps);
1218            /* We only have the interlace problems on
1219               some scanners like the Epson Perfection 2480/2580
1220               at 2400 dpi. */
1221            if (status == SANE_STATUS_GOOD &&
1222                ((pss->pdev->model == PERFECTION2480 && pss->res == 2400) ||
1223                (pss->pdev->model == PERFECTION3490 && pss->res == 3200) ||
1224                (pss->pdev->model == PRISA5000E && pss->res == 1200)))
1225                status = create_Deinterlacer (pss, *pps, pps);
1226            break;
1227        case MD_BILEVELCOLOUR:
1228            status = create_Expander (pss, *pps, pps);
1229            if (status == SANE_STATUS_GOOD)
1230                status = create_RGBRouter (pss, *pps, pps);
1231            if (status == SANE_STATUS_GOOD &&
1232                ((pss->pdev->model == PERFECTION2480 && pss->res == 2400) ||
1233                (pss->pdev->model == PERFECTION3490 && pss->res == 3200) ||
1234                (pss->pdev->model == PRISA5000E && pss->res == 1200)))
1235                status = create_Deinterlacer (pss, *pps, pps);
1236            break;
1237        case MD_GREYSCALE:
1238            if ((pss->pdev->model == PERFECTION2480 && pss->res == 2400) ||
1239                (pss->pdev->model == PERFECTION3490 && pss->res == 3200) ||
1240                (pss->pdev->model == PRISA5000E && pss->res == 1200))
1241                status = create_Deinterlacer (pss, *pps, pps);
1242            break;
1243        case MD_LINEART:
1244            /* The SnapScan creates a negative image by
1245               default... so for the user interface to make sense,
1246               the internal meaning of "negative" is reversed */
1247            if (pss->negative == SANE_FALSE)
1248                status = create_Inverter (pss, *pps, pps);
1249            if (pss->pdev->model == PERFECTION3490 && pss->res == 3200)
1250                status = create_Deinterlacer (pss, *pps, pps);
1251            break;
1252        default:
1253            DBG (DL_MAJOR_ERROR, "%s: bad mode value %d (internal error)\n",
1254                 __func__, mode);
1255            status = SANE_STATUS_INVAL;
1256            break;
1257        }
1258    }
1259    return status;
1260}
1261
1262/*
1263 * Revision 1.21  2005/12/02 19:12:54  oliver-guest
1264 * Another fix for lineart mode for the Epson 3490 @ 3200 DPI
1265 *
1266 * Revision 1.20  2005/11/28 19:28:29  oliver-guest
1267 * Fix for lineart mode of Epson 3490 @ 3200 DPI
1268 *
1269 * Revision 1.19  2005/11/25 17:24:48  oliver-guest
1270 * Fix for Epson 3490 @ 3200 DPI for grayscale and lineart mode
1271 *
1272 * Revision 1.18  2005/11/17 23:47:11  oliver-guest
1273 * Revert previous 'fix', disable 2400 dpi for Epson 3490, use 1600 dpi instead
1274 *
1275 * Revision 1.17  2005/11/17 23:32:23  oliver-guest
1276 * Fixes for Epson 3490 @ 2400 DPI
1277 *
1278 * Revision 1.16  2005/11/10 19:42:02  oliver-guest
1279 * Added deinterlacing for Epson 3490
1280 *
1281 * Revision 1.15  2005/10/31 21:08:47  oliver-guest
1282 * Distinguish between Benq 5000/5000E/5000U
1283 *
1284 * Revision 1.14  2005/10/13 22:43:30  oliver-guest
1285 * Fixes for 16 bit scan mode from Simon Munton
1286 *
1287 * Revision 1.13  2005/10/11 18:47:07  oliver-guest
1288 * Fixes for Epson 3490 and 16 bit scan mode
1289 *
1290 * Revision 1.12  2004/11/14 19:26:38  oliver-guest
1291 * Applied patch from Julien Blache to change ch_past_init from SANE_Int to SANE_Bool
1292 *
1293 * Revision 1.11  2004/11/09 23:17:38  oliver-guest
1294 * First implementation of deinterlacer for Epson scanners at high resolutions (thanks to Brad Johnson)
1295 *
1296 * Revision 1.10  2004/10/03 17:34:36  hmg-guest
1297 * 64 bit platform fixes (bug #300799).
1298 *
1299 * Revision 1.9  2004/04/09 16:18:37  oliver-guest
1300 * Fix initialization of FDSource.bytes_remaining
1301 *
1302 * Revision 1.8  2004/04/09 11:59:02  oliver-guest
1303 * Fixes for pthread implementation
1304 *
1305 * Revision 1.7  2004/04/08 21:53:10  oliver-guest
1306 * Use sanei_thread in snapscan backend
1307 *
1308 * Revision 1.6  2001/12/17 22:51:49  oliverschwartz
1309 * Update to snapscan-20011212 (snapscan 1.4.3)
1310 *
1311 * Revision 1.18  2001/12/12 19:44:59  oliverschwartz
1312 * Clean up CVS log
1313 *
1314 * Revision 1.17  2001/11/27 23:16:17  oliverschwartz
1315 * - Fix color alignment for SnapScan 600
1316 * - Added documentation in snapscan-sources.c
1317 * - Guard against TL_X < BR_X and TL_Y < BR_Y
1318 *
1319 * Revision 1.16  2001/10/08 18:22:02  oliverschwartz
1320 * - Disable quality calibration for Acer Vuego 310F
1321 * - Use sanei_scsi_max_request_size as scanner buffer size
1322 *   for SCSI devices
1323 * - Added new devices to snapscan.desc
1324 *
1325 * Revision 1.15  2001/09/28 15:56:51  oliverschwartz
1326 * - fix hanging for SNAPSCAN300 / VUEGO 310
1327 *
1328 * Revision 1.14  2001/09/28 13:39:16  oliverschwartz
1329 * - Added "Snapscan 300" ID string
1330 * - cleanup
1331 * - more debugging messages in snapscan-sources.c
1332 *
1333 * Revision 1.13  2001/09/18 15:01:07  oliverschwartz
1334 * - Read scanner id string again after firmware upload
1335 *   to identify correct model
1336 * - Make firmware upload work for AGFA scanners
1337 * - Change copyright notice
1338 *
1339 * Revision 1.12  2001/09/09 18:06:32  oliverschwartz
1340 * 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
1341 *
1342 * Revision 1.11  2001/04/13 13:12:18  oliverschwartz
1343 * use absolute_max as expected_read_bytes for PRISA620S
1344 *
1345 * Revision 1.10  2001/04/10 11:04:31  sable
1346 * Adding support for snapscan e40 an e50 thanks to Giuseppe Tanzilli
1347 *
1348 * Revision 1.9  2001/03/17 22:53:21  sable
1349 * Applying Mikael Magnusson patch concerning Gamma correction
1350 * Support for 1212U_2
1351 *
1352 * Revision 1.8  2000/11/28 03:55:07  cbagwell
1353 * Reverting a fix to RGBRouter_remaining to original fix.  This allows
1354 * most scanners to scan at 600 dpi by ignoring insufficient data in
1355 * the RGB circular buffer and always returning size = 1 in those cases.
1356 * This should probably be fixed at a higher level.
1357 *
1358 * Revision 1.7  2000/11/20 01:02:42  cbagwell
1359 * Updates so that USB will continue reading when it receives an EAGAIN error.
1360 * Also, changed RGBRouter_remaining to not be able to return a negative
1361 * value.
1362 *
1363 * Revision 1.6  2000/11/04 01:53:58  cbagwell
1364 * Committing some needed USB updates.  Added extra test logic to detect
1365 * bad bytes_expected values.  Just to help debug faster on scanners
1366 * that tickle the bug.
1367 *
1368 * Revision 1.5  2000/10/30 22:32:20  sable
1369 * Support for vuego310s vuego610s and 1236s
1370 *
1371 * Revision 1.4  2000/10/28 14:16:10  sable
1372 * Bug correction for SnapScan310
1373 *
1374 * Revision 1.3  2000/10/28 14:06:35  sable
1375 * Add support for Acer300f
1376 *
1377 * Revision 1.2  2000/10/13 03:50:27  cbagwell
1378 * Updating to source from SANE 1.0.3.  Calling this version 1.1
1379 * */
1380