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