1/* 2 (c) 2001,2002 Nathan Rutman nathan@gordian.com 10/17/01 3 4 This program is free software; you can redistribute it and/or 5 modify it under the terms of the GNU General Public License as 6 published by the Free Software Foundation; either version 2 of the 7 License, or (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <https://www.gnu.org/licenses/>. 16 17 As a special exception, the authors of SANE give permission for 18 additional uses of the libraries contained in this release of SANE. 19 20 The exception is that, if you link a SANE library with other files 21 to produce an executable, this does not by itself cause the 22 resulting executable to be covered by the GNU General Public 23 License. Your use of that executable is in no way restricted on 24 account of linking the SANE library code into it. 25 26 This exception does not, however, invalidate any other reasons why 27 the executable file might be covered by the GNU General Public 28 License. 29 30 If you submit changes to SANE to the maintainers to be included in 31 a subsequent release, you agree by submitting the changes that 32 those changes may be distributed with this exception intact. 33 34 If you write modifications of your own for SANE, it is your choice 35 whether to permit this exception to apply to your modifications. 36 If you do not wish that, delete this exception notice. 37*/ 38 39/* 40 Communication, calibration, and scanning with the Canon CanoScan FB630U 41 flatbed scanner under linux. 42 43 Reworked into SANE-compatible format. 44 45 The usb-parallel port interface chip is GL640usb, on the far side of 46 which is an LM9830 parallel-port scanner-on-a-chip. 47 48 This code has not been tested on anything other than Linux/i386. 49*/ 50 51#include <errno.h> 52#include <fcntl.h> /* open */ 53#include <stdio.h> 54#include <stdlib.h> 55#include <string.h> 56#include <unistd.h> /* usleep */ 57#include <time.h> 58#include <math.h> /* exp() */ 59#ifdef HAVE_OS2_H 60#include <sys/types.h> /* mode_t */ 61#endif 62#include <sys/stat.h> 63#include "lm9830.h" 64 65#define USB_TYPE_VENDOR (0x02 << 5) 66#define USB_RECIP_DEVICE 0x00 67#define USB_DIR_OUT 0x00 68#define USB_DIR_IN 0x80 69 70/* Assign status and verify a good return code */ 71#define CHK(A) {if( (status = A) != SANE_STATUS_GOOD ) { \ 72 DBG( 1, "Failure on line of %s: %d\n", __FILE__, \ 73 __LINE__ ); return A; }} 74 75 76typedef SANE_Byte byte; 77 78 79/***************************************************** 80 GL640 communication primitives 81 Provides I/O routines to Genesys Logic GL640USB USB-IEEE1284 parallel 82 port bridge. Used in HP3300c, Canon FB630u. 83******************************************************/ 84 85/* Register codes for the bridge. These are NOT the registers for the 86 scanner chip on the other side of the bridge. */ 87typedef enum 88{ 89 GL640_BULK_SETUP = 0x82, 90 GL640_EPP_ADDR = 0x83, 91 GL640_EPP_DATA_READ = 0x84, 92 GL640_EPP_DATA_WRITE = 0x85, 93 GL640_SPP_STATUS = 0x86, 94 GL640_SPP_CONTROL = 0x87, 95 GL640_SPP_DATA = 0x88, 96 GL640_GPIO_OE = 0x89, 97 GL640_GPIO_READ = 0x8a, 98 GL640_GPIO_WRITE = 0x8b 99} 100GL640_Request; 101 102/* Write to the usb-parallel port bridge. */ 103static SANE_Status 104gl640WriteControl (int fd, GL640_Request req, byte * data, unsigned int size) 105{ 106 SANE_Status status; 107 status = sanei_usb_control_msg (fd, 108 /* rqttype */ USB_TYPE_VENDOR | 109 USB_RECIP_DEVICE | USB_DIR_OUT /*0x40? */ , 110 /* rqt */ (size > 1) ? 0x04 : 0x0C, 111 /* val */ (SANE_Int) req, 112 /* ind */ 0, 113 /* len */ size, 114 /* dat */ data); 115 if (status != SANE_STATUS_GOOD) 116 DBG (1, "gl640WriteControl error\n"); 117 return status; 118} 119 120 121/* Read from the usb-parallel port bridge. */ 122static SANE_Status 123gl640ReadControl (int fd, GL640_Request req, byte * data, unsigned int size) 124{ 125 SANE_Status status; 126 status = sanei_usb_control_msg (fd, 127 /* rqttype */ USB_TYPE_VENDOR | 128 USB_RECIP_DEVICE | USB_DIR_IN /*0xc0? */ , 129 /* rqt */ (size > 1) ? 0x04 : 0x0C, 130 /* val */ (SANE_Int) req, 131 /* ind */ 0, 132 /* len */ size, 133 /* dat */ data); 134 if (status != SANE_STATUS_GOOD) 135 DBG (1, "gl640ReadControl error\n"); 136 return status; 137} 138 139 140/* Wrappers to read or write a single byte to the bridge */ 141static inline SANE_Status 142gl640WriteReq (int fd, GL640_Request req, byte data) 143{ 144 return gl640WriteControl (fd, req, &data, 1); 145} 146 147static inline SANE_Status 148gl640ReadReq (int fd, GL640_Request req, byte * data) 149{ 150 return gl640ReadControl (fd, req, data, 1); 151} 152 153 154/* Write USB bulk data 155 setup is an apparently scanner-specific sequence: 156 {(0=read, 1=write), 0x00, 0x00, 0x00, sizelo, sizehi, 0x00, 0x00} 157 hp3400: setup[1] = 0x01 158 fb630u: setup[2] = 0x80 159*/ 160static SANE_Status 161gl640WriteBulk (int fd, byte * setup, byte * data, size_t size) 162{ 163 SANE_Status status; 164 setup[0] = 1; 165 setup[4] = (size) & 0xFF; 166 setup[5] = (size >> 8) & 0xFF; 167 168 CHK (gl640WriteControl (fd, GL640_BULK_SETUP, setup, 8)); 169 170 status = sanei_usb_write_bulk (fd, data, &size); 171 if (status != SANE_STATUS_GOOD) 172 DBG (1, "gl640WriteBulk error\n"); 173 174 return status; 175} 176 177 178/* Read USB bulk data 179 setup is an apparently scanner-specific sequence: 180 {(0=read, 1=write), 0x00, 0x00, 0x00, sizelo, sizehi, 0x00, 0x00} 181 fb630u: setup[2] = 0x80 182*/ 183static SANE_Status 184gl640ReadBulk (int fd, byte * setup, byte * data, size_t size) 185{ 186 SANE_Status status; 187 setup[0] = 0; 188 setup[4] = (size) & 0xFF; 189 setup[5] = (size >> 8) & 0xFF; 190 191 CHK (gl640WriteControl (fd, GL640_BULK_SETUP, setup, 8)); 192 193 status = sanei_usb_read_bulk (fd, data, &size); 194 if (status != SANE_STATUS_GOOD) 195 DBG (1, "gl640ReadBulk error\n"); 196 197 return status; 198} 199 200 201/***************************************************** 202 LM9830 communication primitives 203 parallel-port scanner-on-a-chip. 204******************************************************/ 205 206/* write 1 byte to a LM9830 register address */ 207static SANE_Status 208write_byte (int fd, byte addr, byte val) 209{ 210 SANE_Status status; 211 DBG (14, "write_byte(fd, 0x%02x, 0x%02x);\n", addr, val); 212 CHK (gl640WriteReq (fd, GL640_EPP_ADDR, addr)); 213 CHK (gl640WriteReq (fd, GL640_EPP_DATA_WRITE, val)); 214 return status; 215} 216 217 218/* read 1 byte from a LM9830 register address */ 219static SANE_Status 220read_byte (int fd, byte addr, byte * val) 221{ 222 SANE_Status status; 223 CHK (gl640WriteReq (fd, GL640_EPP_ADDR, addr)); 224 CHK (gl640ReadReq (fd, GL640_EPP_DATA_READ, val)); 225 DBG (14, "read_byte(fd, 0x%02x, &result); /* got %02x */\n", addr, *val); 226 return status; 227} 228 229 230static byte bulk_setup_data[] = { 0, 0, 0x80, 0, 0, 0, 0, 0 }; 231 232/* Bulk write */ 233static SANE_Status 234write_bulk (int fd, unsigned int addr, void *src, size_t count) 235{ 236 SANE_Status status; 237 238 DBG (13, "write_bulk(fd, 0x%02x, buf, 0x%04lx);\n", addr, (u_long) count); 239 240 if (!src) 241 { 242 DBG (1, "write_bulk: bad src\n"); 243 return SANE_STATUS_INVAL; 244 } 245 246 /* destination address */ 247 CHK (gl640WriteReq (fd, GL640_EPP_ADDR, addr)); 248 /* write */ 249 CHK (gl640WriteBulk (fd, bulk_setup_data, src, count)); 250 return status; 251} 252 253 254/* Bulk read */ 255static SANE_Status 256read_bulk (int fd, unsigned int addr, void *dst, size_t count) 257{ 258 SANE_Status status; 259 260 DBG (13, "read_bulk(fd, 0x%02x, buf, 0x%04lx);\n", addr, (u_long) count); 261 262 if (!dst) 263 { 264 DBG (1, "read_bulk: bad dest\n"); 265 return SANE_STATUS_INVAL; 266 } 267 268 /* destination address */ 269 CHK (gl640WriteReq (fd, GL640_EPP_ADDR, addr)); 270 /* read */ 271 CHK (gl640ReadBulk (fd, bulk_setup_data, dst, count)); 272 return status; 273} 274 275 276 277/***************************************************** 278 useful macro routines 279******************************************************/ 280 281/* write a 16-bit int to two sequential registers */ 282static SANE_Status 283write_word (int fd, unsigned int addr, unsigned int data) 284{ 285 SANE_Status status; 286 /* MSB */ 287 CHK (write_byte (fd, addr, (data >> 8) & 0xff)); 288 /* LSB */ 289 CHK (write_byte (fd, addr + 1, data & 0xff)); 290 return status; 291} 292 293 294/* write multiple bytes, one at a time (non-bulk) */ 295static SANE_Status 296write_many (int fd, unsigned int addr, const byte *src, size_t count) 297{ 298 SANE_Status status; 299 size_t i; 300 301 DBG (14, "multi write %lu\n", (u_long) count); 302 for (i = 0; i < count; i++) 303 { 304 DBG (15, " %04lx:%02x", (u_long) (addr + i), src[i]); 305 status = write_byte (fd, addr + i, src[i]); 306 if (status != SANE_STATUS_GOOD) 307 { 308 DBG (15, "\n"); 309 return status; 310 } 311 } 312 DBG (15, "\n"); 313 return SANE_STATUS_GOOD; 314} 315 316 317/* read multiple bytes, one at a time (non-bulk) */ 318static SANE_Status 319read_many (int fd, unsigned int addr, void *dst, size_t count) 320{ 321 SANE_Status status; 322 size_t i; 323 byte val; 324 325 DBG (14, "multi read %lu\n", (u_long) count); 326 for (i = 0; i < count; i++) 327 { 328 status = read_byte (fd, addr + i, &val); 329 ((byte *) dst)[i] = val; 330 DBG (15, " %04lx:%02x", (u_long) (addr + i), ((byte *) dst)[i]); 331 /* on err, return number of success */ 332 if (status != SANE_STATUS_GOOD) 333 { 334 DBG (15, "\n"); 335 return status; 336 } 337 } 338 DBG (15, "\n"); 339 return SANE_STATUS_GOOD; 340} 341 342 343/* Poll addr until result & mask = val */ 344static int 345read_poll_flag (int fd, 346 unsigned int addr, unsigned int mask, unsigned int val) 347{ 348 SANE_Status status; 349 byte result = 0; 350 time_t start_time = time (NULL); 351 352 DBG (12, "read_poll_flag...\n"); 353 do 354 { 355 status = read_byte (fd, addr, &result); 356 if (status != SANE_STATUS_GOOD) 357 return -1; 358 /* Give it a minute */ 359 if ((time (NULL) - start_time) > 60) 360 { 361 DBG (1, "read_poll_flag: timed out (%d)\n", result); 362 return -1; 363 } 364 usleep (100000); 365 } 366 while ((result & mask) != val); 367 return result; 368} 369 370 371/* Keep reading addr until results >= min */ 372static int 373read_poll_min (int fd, unsigned int addr, unsigned int min) 374{ 375 SANE_Status status; 376 byte result; 377 time_t start_time = time (NULL); 378 379 DBG (12, "waiting...\n"); 380 do 381 { 382 status = read_byte (fd, addr, &result); 383 if (status != SANE_STATUS_GOOD) 384 return -1; 385 /* Give it a minute */ 386 if ((time (NULL) - start_time) > 60) 387 { 388 DBG (1, "read_poll_min: timed out (%d < %d)\n", result, min); 389 return -1; 390 } 391 /* no sleep here, or calibration gets unhappy. */ 392 } 393 while (result < min); 394 return result; 395} 396 397 398/* Bulk read "ks" kilobytes + "remainder" bytes of data, to a buffer if the 399 buffer is valid. */ 400static int 401read_bulk_size (int fd, int ks, int remainder, byte * dest, int destsize) 402{ 403 byte *buf; 404 int bytes = (ks - 1) * 1024 + remainder; 405 int dropdata = ((dest == 0) || (destsize < bytes)); 406 407 if (bytes < 0) 408 { 409 DBG (1, "read_bulk_size: invalid size %02x (%d)\n", ks, bytes); 410 return -1; 411 } 412 if (destsize && (destsize < bytes)) 413 { 414 DBG (3, "read_bulk_size: more data than buffer (%d/%d)\n", 415 destsize, bytes); 416 bytes = destsize; 417 } 418 419 if (bytes == 0) 420 return 0; 421 422 if (dropdata) 423 { 424 buf = malloc (bytes); 425 DBG (3, " ignoring data "); 426 } 427 else 428 buf = dest; 429 430 read_bulk (fd, 0x00, buf, bytes); 431 432 if (dropdata) 433 free (buf); 434 return bytes; 435} 436 437 438 439/***************************************************** 440 441 fb630u calibration and scan 442 443******************************************************/ 444 445/* data structures and constants */ 446 447typedef struct CANON_Handle 448{ 449 int fd; /* scanner fd */ 450 int x1, x2, y1, y2; /* in pixels, 600 dpi */ 451 int width, height; /* at scan resolution */ 452 int resolution; /* dpi */ 453 char *fname; /* output file name */ 454 FILE *fp; /* output file pointer (for reading) */ 455 char *buf, *ptr; /* data buffer */ 456 unsigned char gain; /* static analog gain, 0 - 31 */ 457 double gamma; /* gamma correction */ 458 int flags; 459#define FLG_GRAY 0x01 /* grayscale */ 460#define FLG_FORCE_CAL 0x02 /* force calibration */ 461#define FLG_BUF 0x04 /* save scan to buffer instead of file */ 462#define FLG_NO_INTERLEAVE 0x08 /* don't interleave r,g,b pixels; leave them 463 in row format */ 464#define FLG_PPM_HEADER 0x10 /* include PPM header in scan file */ 465} 466CANON_Handle; 467 468 469/* offset/gain calibration file name */ 470#define CAL_FILE_OGN "/tmp/canon.cal" 471 472/* at 600 dpi */ 473#define CANON_MAX_WIDTH 5100 /* 8.5in */ 474/* this may not be right */ 475#define CANON_MAX_HEIGHT 7000 /* 11.66in */ 476 477/* scanline end-of-line data byte, returned after each r,g,b segment, 478 specific to the FB630u */ 479#define SCANLINE_END 0x0c 480 481 482static const byte seq002[] = 483 { /*r08 */ 0x04, /*300 dpi */ 0x1a, 0x00, 0x0d, 0x4c, 0x2f, 0x00, 0x01, 484/*r10 */ 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x25, 0x00, 4850x4b, /*r20 */ 0x15, 0xe0, /*data px start */ 0x00, 0x4b, /*data px end */ 0x14, 0x37, 0x15, 0x00 }; 486 487static const byte seq003[] = 488 { 0x02, 0x00, 0x00, /*lights out */ 0x03, 0xff, 0x00, 0x01, 0x03, 0xff, 4890x00, 0x01, 0x03, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 4900x1d, 0x00, 0x13, 0x04, 0x1a, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x57, 0x02, 0x00, 0x3c, 0x35, 0x94, 4910x00, 0x10, 0x08, 0x3f, 0x2b, 0x91, 0x00, 0x00, 0x01, 0x00, 0x80, 0x00 }; 492 493 494/* Scanner init, called at calibration and scan time. Returns 1 if this 495 was the first time the scanner was plugged in, 0 afterward, and 496 -1 on error. */ 497static int 498init (int fd) 499{ 500 byte result, rv; 501 502 if (gl640WriteReq (fd, GL640_GPIO_OE, 0x71) != SANE_STATUS_GOOD) { 503 DBG(1, "Initial write request failed.\n"); 504 return -1; 505 } 506 /* Gets 0x04 or 0x05 first run, gets 0x64 subsequent runs. */ 507 if (gl640ReadReq (fd, GL640_GPIO_READ, &rv) != SANE_STATUS_GOOD) { 508 DBG(1, "Initial read request failed.\n"); 509 return -1; 510 } 511 gl640WriteReq (fd, GL640_GPIO_OE, 0x70); 512 513 DBG (2, "init query: %x\n", rv); 514 if (rv != 0x64) 515 { 516 gl640WriteReq (fd, GL640_GPIO_WRITE, 0x00); 517 gl640WriteReq (fd, GL640_GPIO_WRITE, 0x40); 518 } 519 520 gl640WriteReq (fd, GL640_SPP_DATA, 0x99); 521 gl640WriteReq (fd, GL640_SPP_DATA, 0x66); 522 gl640WriteReq (fd, GL640_SPP_DATA, 0xcc); 523 gl640WriteReq (fd, GL640_SPP_DATA, 0x33); 524 /* parallel port setting */ 525 write_byte (fd, PARALLEL_PORT, 0x06); 526 /* sensor control settings */ 527 write_byte (fd, 0x0b, 0x0d); 528 write_byte (fd, 0x0c, 0x4c); 529 write_byte (fd, 0x0d, 0x2f); 530 read_byte (fd, 0x0b, &result); /* wants 0d */ 531 read_byte (fd, 0x0c, &result); /* wants 4c */ 532 read_byte (fd, 0x0d, &result); /* wants 2f */ 533 /* parallel port noise filter */ 534 write_byte (fd, 0x70, 0x73); 535 536 DBG (2, "init post-reset: %x\n", rv); 537 /* Returns 1 if this was the first time the scanner was plugged in. */ 538 return (rv != 0x64); 539} 540 541 542/* Turn off the lamps */ 543static void 544lights_out (int fd) 545{ 546 write_word (fd, LAMP_R_ON, 0x3fff); 547 write_word (fd, LAMP_R_OFF, 0x0001); 548 write_word (fd, LAMP_G_ON, 0x3fff); 549 write_word (fd, LAMP_G_OFF, 0x0001); 550 write_word (fd, LAMP_B_ON, 0x3fff); 551 write_word (fd, LAMP_B_OFF, 0x0001); 552} 553 554 555/* Do the scan and save the resulting image as r,g,b interleaved PPM 556 file. */ 557static SANE_Status 558do_scan (CANON_Handle * s) 559{ 560 SANE_Status status = SANE_STATUS_GOOD; 561 int numbytes, datasize, level = 0, line = 0, pixel = 0; 562 byte *buf, *ptr, *redptr; 563 FILE *fp; 564 565#define BUFSIZE 0xf000 566 buf = malloc (BUFSIZE); 567 if (!buf) 568 return SANE_STATUS_NO_MEM; 569 570 if (s->flags & FLG_BUF) 571 { 572 /* read the whole thing into buf */ 573 if (!s->buf) 574 return SANE_STATUS_NO_MEM; 575 s->ptr = s->buf; 576 fp = NULL; 577 } 578 else 579 { 580 fp = fopen (s->fname, "w"); 581 if (!fp) 582 { 583 free (buf); 584 DBG (1, "err:%s when opening %s\n", strerror (errno), s->fname); 585 return SANE_STATUS_IO_ERROR; 586 } 587 } 588 if (fp && (s->flags & FLG_PPM_HEADER)) 589 /* PPM format header */ 590 fprintf (fp, "P6\n%d %d\n255\n", s->width, s->height); 591 592 /* lights off */ 593 write_byte (s->fd, COMMAND, 0x08); 594 /* lights on */ 595 write_byte (s->fd, COMMAND, 0x00); 596 /* begin scan */ 597 write_byte (s->fd, COMMAND, 0x03); 598 599 ptr = redptr = buf; 600 while (line < s->height) 601 { 602 datasize = read_poll_min (s->fd, IMAGE_DATA_AVAIL, 2); 603 if (datasize < 0) 604 { 605 DBG (1, "no data\n"); 606 break; 607 } 608 DBG (12, "scan line %d %dk\n", line, datasize - 1); 609 /* Read may cause scan head to move */ 610 numbytes = read_bulk_size (s->fd, datasize, 0, ptr, BUFSIZE - level); 611 if (numbytes < 0) 612 { 613 status = SANE_STATUS_INVAL; 614 break; 615 } 616 /* Data coming back is "width" bytes Red data followed by 0x0c, 617 width bytes Green, 0x0c, width bytes Blue, 0x0c, repeat for 618 "height" lines. */ 619 if (s->flags & FLG_NO_INTERLEAVE) 620 { 621 /* number of full lines */ 622 line += (numbytes + level) / (s->width * 3); 623 /* remainder (partial line) */ 624 level = (numbytes + level) % (s->width * 3); 625 /* but if last line, don't store extra */ 626 if (line >= s->height) 627 numbytes -= (line - s->height) * s->width * 3 + level; 628 if (fp) 629 fwrite (buf, 1, numbytes, fp); 630 else 631 { 632 memcpy (s->ptr, buf, numbytes); 633 s->ptr += numbytes; 634 } 635 } 636 else 637 { 638 /* Contorsions to convert data from line-by-line RGB to 639 byte-by-byte RGB, without reading in the whole buffer first. 640 We use the sliding window redptr with the temp buffer buf. */ 641 ptr += numbytes; /* point to the end of data */ 642 /* while we have RGB triple data */ 643 while (redptr + s->width + s->width <= ptr) 644 { 645 if (*redptr == SCANLINE_END) 646 DBG (13, "-%d- ", pixel); 647 if (fp) 648 { 649 /* for PPM binary (P6), 3-byte RGB pixel */ 650 fwrite (redptr, 1, 1, fp); /* Red */ 651 fwrite (redptr + s->width, 1, 1, fp); /* Green */ 652 fwrite (redptr + s->width + s->width, 1, 1, fp); /* Blue */ 653 /* for PPM ascii (P3) 654 fprintf(fp, "%3d %3d %3d\n", *redptr, 655 *(redptr + s->width), 656 *(redptr + s->width + s->width)); 657 */ 658 } 659 else 660 { 661 /* R */ *s->ptr = *redptr; 662 s->ptr++; 663 /* G */ *s->ptr = *(redptr + s->width); 664 s->ptr++; 665 /* B */ *s->ptr = *(redptr + s->width + s->width); 666 s->ptr++; 667 } 668 redptr++; 669 pixel++; 670 if (pixel && !(pixel % s->width)) 671 { 672 /* end of a line, move redptr to the next Red section */ 673 line++; 674 redptr += s->width + s->width; 675#if 0 676 /* progress */ 677 printf ("%2d%%\r", line * 100 / s->height); 678 fflush (stdout); 679#endif 680 /* don't record any extra */ 681 if (line >= s->height) 682 break; 683 } 684 } 685 /* keep the extra around for next time */ 686 level = ptr - redptr; 687 if (level < 0) 688 level = 0; 689 memmove (buf, redptr, level); 690 ptr = buf + level; 691 redptr = buf; 692 } 693 } 694 695 if (fp) 696 { 697 fclose (fp); 698 DBG (6, "created scan file %s\n", s->fname); 699 } 700 free (buf); 701 DBG (6, "%d lines, %d pixels, %d extra bytes\n", line, pixel, level); 702 703 /* motor off */ 704 write_byte (s->fd, COMMAND, 0x00); 705 706 return status; 707} 708 709 710static int 711wait_for_return (int fd) 712{ 713 return read_poll_flag (fd, STATUS, STATUS_HOME, STATUS_HOME); 714} 715 716 717static SANE_Status compute_ogn (char *calfilename); 718 719 720/* This is the calibration routine Win2k goes through when the scanner is 721 first plugged in. 722 Original usb trace from Win2k with USBSnoopy ("usb sniffer for w2k" 723 http://benoit.papillault.free.fr/speedtouch/sniff-2000.en.php3) 724 */ 725static int 726plugin_cal (CANON_Handle * s) 727{ 728 SANE_Status status; 729 unsigned int temp; 730 byte result; 731 byte *buf; 732 int fd = s->fd; 733 734 DBG (6, "Calibrating\n"); 735 736 /* reserved? */ 737 read_byte (fd, 0x69, &result); /* wants 02 */ 738 739 /* parallel port setting */ 740 write_byte (fd, PARALLEL_PORT, 0x06); 741 742 write_many (fd, 0x08, seq002, sizeof (seq002)); 743 /* addr 0x28 isn't written */ 744 write_many (fd, 0x29, seq003, sizeof (seq003)); 745 /* Verification */ 746 buf = malloc (0x400); 747 read_many (fd, 0x08, buf, sizeof (seq002)); 748 if (memcmp (seq002, buf, sizeof (seq002))) 749 DBG (1, "seq002 verification error\n"); 750 /* addr 0x28 isn't read */ 751 read_many (fd, 0x29, buf, sizeof (seq003)); 752 if (memcmp (seq003, buf, sizeof (seq003))) 753 DBG (1, "seq003 verification error\n"); 754 755 /* parallel port noise filter */ 756 write_byte (fd, 0x70, 0x73); 757 758 lights_out (fd); 759 760 /* Home motor */ 761 read_byte (fd, STATUS, &result); /* wants 2f or 2d */ 762 if (!(result & STATUS_HOME) /*0x2d */ ) 763 write_byte (fd, COMMAND, 0x02); 764 765 wait_for_return (fd); 766 767 /* Motor forward */ 768 write_byte (fd, COMMAND, 0x01); 769 usleep (600000); 770 read_byte (fd, STATUS, &result); /* wants 0c or 2c */ 771 read_byte (fd, STATUS, &result); /* wants 0c */ 772 /* Return home */ 773 write_byte (fd, COMMAND, 0x02); 774 775 /* Gamma tables */ 776 /* Linear gamma */ 777 for (temp = 0; temp < 0x0400; temp++) 778 buf[temp] = temp / 4; 779 /* Gamma Red */ 780 write_byte (fd, DATAPORT_TARGET, DP_R | DP_GAMMA); 781 write_word (fd, DATAPORT_ADDR, DP_WRITE); 782 write_bulk (fd, DATAPORT, buf, 0x0400); 783 /* Gamma Green */ 784 write_byte (fd, DATAPORT_TARGET, DP_G | DP_GAMMA); 785 write_word (fd, DATAPORT_ADDR, DP_WRITE); 786 write_bulk (fd, DATAPORT, buf, 0x0400); 787 /* Gamma Blue */ 788 write_byte (fd, DATAPORT_TARGET, DP_B | DP_GAMMA); 789 write_word (fd, DATAPORT_ADDR, DP_WRITE); 790 write_bulk (fd, DATAPORT, buf, 0x0400); 791 792 /* Read back gamma tables. I suppose I should check results... */ 793 /* Gamma Red */ 794 write_byte (fd, DATAPORT_TARGET, DP_R | DP_GAMMA); 795 write_word (fd, DATAPORT_ADDR, DP_READ); 796 read_bulk (fd, DATAPORT, buf, 0x0400); 797 /* Gamma Green */ 798 write_byte (fd, DATAPORT_TARGET, DP_G | DP_GAMMA); 799 write_word (fd, DATAPORT_ADDR, DP_READ); 800 read_bulk (fd, DATAPORT, buf, 0x0400); 801 /* Gamma Blue */ 802 write_byte (fd, DATAPORT_TARGET, DP_B | DP_GAMMA); 803 write_word (fd, DATAPORT_ADDR, DP_READ); 804 read_bulk (fd, DATAPORT, buf, 0x0400); 805 free (buf); 806 807 /* Make sure STATUS_HOME */ 808 read_byte (fd, STATUS, &result); /* wants 0e */ 809 /* stepper forward */ 810 write_byte (fd, COMMAND, 0x01); 811 read_byte (fd, STATUS, &result); /* wants 0c */ 812 /* not sure if this rigid read/write pattern is required */ 813 read_byte (fd, CLOCK_DIV, &result); /* wants 04 */ 814 write_byte (fd, CLOCK_DIV, 0x04); 815 read_byte (fd, STEP_SIZE, &result); /* wants 04 */ 816 write_byte (fd, STEP_SIZE, 0x3f); 817 read_byte (fd, 0x47, &result); /* wants 1a */ 818 write_byte (fd, 0x47, 0xff); 819 read_byte (fd, FAST_STEP, &result); /* wants 01 */ 820 write_byte (fd, FAST_STEP, 0x01); 821 read_byte (fd, 0x49, &result); /* wants 04 */ 822 write_byte (fd, 0x49, 0x04); 823 read_byte (fd, SKIP_STEPS, &result); /* wants 00 */ 824 write_byte (fd, SKIP_STEPS, 0x00); 825 read_byte (fd, 0x4b, &result); /* wants 00 */ 826 write_byte (fd, 0x4b, 0xc8); 827 read_byte (fd, BUFFER_LIMIT, &result); /* wants 57 */ 828 write_byte (fd, BUFFER_LIMIT, 0x04); 829 read_byte (fd, BUFFER_RESUME, &result); /* wants 02 */ 830 write_byte (fd, BUFFER_RESUME, 0x02); 831 read_byte (fd, REVERSE_STEPS, &result); /* wants 00 */ 832 write_byte (fd, REVERSE_STEPS, 0x00); 833 write_byte (fd, STEP_PWM, 0x1f); 834 835 /* Reset motor */ 836 write_byte (fd, COMMAND, 0x08); 837 write_byte (fd, COMMAND, 0x00); 838 /* Scan */ 839 write_byte (fd, COMMAND, 0x03); 840 /* Wants 02 or 03, gets a bunch of 0's first */ 841 read_poll_min (fd, IMAGE_DATA_AVAIL, 2); 842 write_byte (fd, COMMAND, 0x00); 843 844 write_byte (fd, STEP_PWM, 0x3f); 845 write_byte (fd, CLOCK_DIV, 0x04); 846 /* 300 dpi */ 847 write_word (fd, STEP_SIZE, 0x041a); 848 write_word (fd, FAST_STEP, 0x0104); 849 /* Don't skip the black/white calibration area at the bottom of the 850 scanner. */ 851 write_word (fd, SKIP_STEPS, 0x0000); 852 write_byte (fd, BUFFER_LIMIT, 0x57); 853 write_byte (fd, BUFFER_RESUME, 0x02); 854 write_byte (fd, REVERSE_STEPS, 0x00); 855 write_byte (fd, BUFFER_LIMIT, 0x09); 856 write_byte (fd, STEP_PWM, 0x1f); 857 read_byte (fd, MICROSTEP, &result); /* wants 13, active */ 858 write_byte (fd, MICROSTEP, 0x03 /* tristate */ ); 859 860 /* Calibration data taken under 3 different lighting conditions */ 861 /* dark */ 862 write_word (fd, LAMP_R_ON, 0x0017); 863 write_word (fd, LAMP_R_OFF, 0x0100); 864 write_word (fd, LAMP_G_ON, 0x0017); 865 write_word (fd, LAMP_G_OFF, 0x0100); 866 write_word (fd, LAMP_B_ON, 0x0017); 867 write_word (fd, LAMP_B_OFF, 0x0100); 868 /* coming in, we've got 300dpi, 869 data px start : 0x004b 870 data px end : 0x1437 for a total of 5100(13ec) 600-dpi pixels, 871 (8.5 inches) or 2550 300-dpi pixels (7653 bytes). 872 Interestingly, the scan head never moves, no matter how many rows 873 are read. */ 874 s->width = 2551; 875 s->height = 1; 876 s->flags = FLG_BUF | FLG_NO_INTERLEAVE; 877 s->buf = malloc (s->width * s->height * 3); 878 /* FIXME do something with this data */ 879 CHK (do_scan (s)); 880 881 /* Lighting */ 882 /* medium */ 883 write_word (fd, LAMP_R_ON, 0x0017); 884 write_word (fd, LAMP_R_OFF, 0x0200); 885 write_word (fd, LAMP_G_ON, 0x0017); 886 write_word (fd, LAMP_G_OFF, 0x01d7 /* also 01db */ ); 887 write_word (fd, LAMP_B_ON, 0x0017); 888 write_word (fd, LAMP_B_OFF, 0x01af /* also 01b2 */ ); 889 /* FIXME do something with this data */ 890 CHK (do_scan (s)); 891 892 /* Lighting */ 893 /* bright */ 894 write_word (fd, LAMP_R_ON, 0x0017); 895 write_word (fd, LAMP_R_OFF, 0x0e8e /* also 1040 */ ); 896 write_word (fd, LAMP_G_ON, 0x0017); 897 write_word (fd, LAMP_G_OFF, 0x0753 /* also 0718 */ ); 898 write_word (fd, LAMP_B_ON, 0x0017); 899 write_word (fd, LAMP_B_OFF, 0x03f8 /* also 040d */ ); 900 /* FIXME do something with this data */ 901 CHK (do_scan (s)); 902 free (s->buf); 903 s->buf = NULL; 904 905 /* The trace gets a little iffy from here on out since the log files 906 are missing different urb's. This is kind of a puzzled-out 907 compilation. */ 908 909 write_byte (fd, MICROSTEP, 0x13 /* pins active */ ); 910 write_byte (fd, STEP_PWM, 0x3f); 911 read_byte (fd, STATUS, &result); /* wants 0c */ 912 913 /* Stepper home */ 914 write_byte (fd, COMMAND, 0x02); 915 /* Step size */ 916 write_word (fd, STEP_SIZE, 0x041a /* 300 dpi */ ); 917 /* Skip steps */ 918 write_word (fd, SKIP_STEPS, 0x0000); 919 /* Pause buffer levels */ 920 write_byte (fd, BUFFER_LIMIT, 0x57); 921 /* Resume buffer levels */ 922 write_byte (fd, BUFFER_RESUME, 0x02); 923 924 wait_for_return (fd); 925 /* stepper forward small */ 926 write_byte (fd, COMMAND, 0x01); 927 read_byte (fd, STATUS, &result); /* wants 0c */ 928 usleep (200000); 929 write_byte (fd, STEP_PWM, 0x1f); 930 931 /* Read in cal strip at bottom of scanner (to adjust gain/offset 932 tables. Note that this isn't the brightest lighting condition.) 933 At 300 dpi: black rows 0-25; white rows 30-75; beginning 934 of glass 90. 935 This produces 574k of data, so save it to a temp file. */ 936 if (!s->fname) 937 { 938 DBG (1, "No temp filename!\n"); 939 s->fname = strdup ("/tmp/cal.XXXXXX"); 940 941 /* FIXME: we should be using fd, not discarding it, and also checking for error! */ 942 int fd = mkstemp (s->fname); 943 close(fd); 944 } 945 s->width = 2551; 946 s->height = 75; 947 s->flags = FLG_PPM_HEADER | FLG_NO_INTERLEAVE; 948 CHK (do_scan (s)); 949 compute_ogn (s->fname); 950 unlink (s->fname); 951 952 write_byte (fd, STEP_PWM, 0x3f); 953 /* stepper home */ 954 write_byte (fd, COMMAND, 0x02); 955 956 /* discard the remaining data */ 957 read_byte (fd, IMAGE_DATA_AVAIL, &result); /* wants 42,4c */ 958 if (result > 1) 959 { 960 read_bulk_size (fd, result, 0, 0, 0); 961 DBG (11, "read %dk extra\n", result); 962 } 963 read_byte (fd, 0x69, &result); /* wants 02 */ 964 write_byte (fd, 0x69, 0x0a); 965 966 lights_out (fd); 967 init (fd); 968 969#if 0 970 /* Repeatedly send this every 1 second. Button scan? FIXME */ 971 gl640ReadReq (fd, GL640_GPIO_READ, &result); /* wants 00 */ 972#endif 973 974 return 0; 975} 976 977 978/* The number of regions in the calibration strip (black & white). */ 979#define NREGIONS 2 980 981/* Compute the offset/gain table from the calibration strip. This is 982 somewhat more complicated than necessary because I don't hard-code the 983 strip widths; I try to figure out the regions based on the scan data. 984 Theoretically, the region-finder should work for any number of distinct 985 regions (but there are only 2 on this scanner.) 986 This produces the CAL_FILE_OGN file, the final offset/gain table. */ 987static SANE_Status 988compute_ogn (char *calfilename) 989{ 990 byte *linebuf, *oldline, *newline; 991 mode_t oldmask; 992 FILE *fp; 993 int width, height, nlines = 0, region = -1, i, transition = 1, badcnt; 994 int pct; 995 int reglines[NREGIONS]; 996 float *avg; 997 float max_range[3], tmp1, tmp2; 998 999 fp = fopen (calfilename, "r"); 1000 if (!fp) 1001 { 1002 DBG (1, "open %s\n", calfilename); 1003 return SANE_STATUS_EOF; 1004 } 1005 fscanf (fp, "P6 %d %d %*d ", &width, &height); 1006 DBG (12, "cal file %s %dx%d\n", calfilename, width, height); 1007 width = width * 3; /* 1 byte each of r, g, b */ 1008 /* make a buffer holding 2 lines of data */ 1009 linebuf = calloc (width * 2, sizeof (linebuf[0])); 1010 /* first line is data read buffer */ 1011 newline = linebuf; 1012 /* second line is a temporary holding spot in case the next line read 1013 is the black/white transition, in which case we'll disregard this 1014 one. */ 1015 oldline = linebuf + width; 1016 /* column averages per region */ 1017 avg = calloc (width * NREGIONS, sizeof (avg[0])); 1018 1019 while (nlines < height) 1020 { 1021 if (fread (newline, 1, width, fp) != (size_t) width) 1022 break; 1023 nlines++; 1024 /* Check if new line is majorly different than old. 1025 Criteria is 10 pixels differing by more than 10%. */ 1026 badcnt = 0; 1027 for (i = 0; i < width; i++) 1028 { 1029 pct = newline[i] - oldline[i]; 1030 /* Fix by M.Reinelt <reinelt@eunet.at> 1031 * do NOT use 10% (think of a dark area with 1032 * oldline=4 and newline=5, which is a change of 20% !! 1033 * Use an absolute difference of 10 as criteria 1034 */ 1035 if (pct < -10 || pct > 10) 1036 { 1037 badcnt++; 1038 DBG (16, "pix%d[%d/%d] ", i, newline[i], oldline[i]); 1039 } 1040 } 1041 DBG (13, "line %d changed %d\n", nlines, badcnt); 1042 if ((badcnt > 10) || (nlines == height)) 1043 { 1044 /* End of region. Lines are different or end of data. */ 1045 transition++; 1046 if (transition == 1) 1047 DBG (12, "Region %d lines %d-%d\n", 1048 region, nlines - reglines[region], nlines - 1); 1049 } 1050 else 1051 { 1052 /* Lines are similar, so still in region. */ 1053 if (transition) 1054 { 1055 /* There was just a transition, so this is the start of a 1056 new region. */ 1057 region++; 1058 if (region >= NREGIONS) 1059 /* Too many regions detected. Err below. */ 1060 break; 1061 transition = 0; 1062 reglines[region] = 0; 1063 } 1064 /* Add oldline to the current region's average */ 1065 for (i = 0; i < width; i++) 1066 avg[i + region * width] += oldline[i]; 1067 reglines[region]++; 1068 } 1069 /* And newline becomes old */ 1070 memcpy (oldline, newline, width); 1071 } 1072 fclose (fp); 1073 free (linebuf); 1074 region++; /* now call it number of regions instead of index */ 1075 DBG (11, "read %d lines as %d regions\n", nlines, region); 1076 1077 /* Check to see if we screwed up */ 1078 if (region != NREGIONS) 1079 { 1080 DBG (1, "Warning: gain/offset compute failed.\n" 1081 "Found %d regions instead of %d.\n", region, NREGIONS); 1082 for (i = 0; i < region; i++) 1083 DBG (1, " Region %d: %d lines\n", 1084 i, (i >= NREGIONS) ? -1 : reglines[i]); 1085 free (avg); 1086 return SANE_STATUS_UNSUPPORTED; 1087 } 1088 1089 /* Now we've got regions and sums. Find averages and range. */ 1090 max_range[0] = max_range[1] = max_range[2] = 0.0; 1091 for (i = 0; i < width; i++) 1092 { 1093 /* Convert sums to averages */ 1094 /* black region */ 1095 tmp1 = avg[i] /= reglines[0]; 1096 /* white region */ 1097 tmp2 = avg[i + width] /= reglines[1]; 1098 /* Track largest range for each color. 1099 If image is interleaved, use 'i%3', if not, 'i/(width/3)' */ 1100 if ((tmp2 - tmp1) > max_range[i / (width / 3)]) 1101 { 1102 max_range[i / (width / 3)] = tmp2 - tmp1; 1103 DBG (14, "max %d@%d %f-%f=%f\n", 1104 i / (width / 3), i, tmp2, tmp1, tmp2 - tmp1); 1105 } 1106 } 1107 DBG (13, "max range r %f\n", max_range[0]); 1108 DBG (13, "max range g %f\n", max_range[1]); 1109 DBG (13, "max range b %f\n", max_range[2]); 1110 1111 /* Set umask to world r/w so other users can overwrite common cal... */ 1112 oldmask = umask (0); 1113 fp = fopen (CAL_FILE_OGN, "w"); 1114 /* ... and set it back. */ 1115 umask (oldmask); 1116 if (!fp) 1117 { 1118 DBG (1, "open " CAL_FILE_OGN); 1119 free (avg); 1120 return SANE_STATUS_IO_ERROR; 1121 } 1122 1123 /* Finally, compute offset and gain */ 1124 for (i = 0; i < width; i++) 1125 { 1126 int gain, offset; 1127 byte ogn[2]; 1128 1129 /* skip line termination flags */ 1130 if (!((i + 1) % (width / 3))) 1131 { 1132 DBG (13, "skip scanline EOL %d/%d\n", i, width); 1133 continue; 1134 } 1135 1136 /* Gain multiplier: 1137 255 : 1.5 times brighter 1138 511 : 2 times brighter 1139 1023: 3 times brighter */ 1140#if 1 1141 /* Original gain/offset */ 1142 gain = 512 * ((max_range[i / (width / 3)] / 1143 (avg[i + width] - avg[i])) - 1); 1144 offset = avg[i]; 1145#else 1146 /* This doesn't work for some people. For instance, a negative 1147 offset would be bad. */ 1148 1149 /* Enhanced offset and gain calculation by M.Reinelt <reinelt@eunet.at> 1150 * These expressions were found by an iterative calibration process, 1151 * by changing gain and offset values for every pixel until the desired 1152 * values for black and white were reached, and finding an approximation 1153 * formula. 1154 * Note that offset is linear, but gain isn't! 1155 */ 1156 offset = (double)3.53 * avg[i] - 125; 1157 gain = (double)3861.0 * exp(-0.0168 * (avg[i + width] - avg[i])); 1158#endif 1159 1160 DBG (14, "%d wht=%f blk=%f diff=%f gain=%d offset=%d\n", i, 1161 avg[i + width], avg[i], avg[i + width] - avg[i], gain, offset); 1162 /* 10-bit gain, 6-bit offset (subtractor) in two bytes */ 1163 ogn[0] = (byte) (((offset << 2) + (gain >> 8)) & 0xFF); 1164 ogn[1] = (byte) (gain & 0xFF); 1165 fwrite (ogn, sizeof (byte), 2, fp); 1166 /* Annoyingly, we seem to use ogn data at 600dpi, while we scanned 1167 at 300, so double our file. Much easier than doubling at the 1168 read. */ 1169 fwrite (ogn, sizeof (byte), 2, fp); 1170 } 1171 1172 fclose (fp); 1173 free (avg); 1174 return SANE_STATUS_GOOD; 1175} 1176 1177static int 1178check_ogn_file (void) 1179{ 1180 FILE *fp; 1181 fp = fopen (CAL_FILE_OGN, "r"); 1182 if (fp) 1183 { 1184 fclose (fp); 1185 return 1; 1186 } 1187 return 0; 1188} 1189 1190/* Load or fake the offset/gain table */ 1191static void 1192install_ogn (int fd) 1193{ 1194 int temp; 1195 byte *buf; 1196 FILE *fp; 1197 1198 /* 8.5in at 600dpi = 5104 pixels in scan head 1199 10-bit gain + 6-bit offset = 2 bytes per pixel, so 10208 bytes */ 1200 buf = malloc (10208); 1201 1202 fp = fopen (CAL_FILE_OGN, "r"); 1203 if (fp) 1204 { 1205 fread (buf, 2, 5100, fp); 1206 /* screw the last 4 pixels */ 1207 } 1208 else 1209 { 1210 /* Make up the gain/offset data. */ 1211#define GAIN 256 /* 1.5x */ 1212#define OFFSET 0 1213 for (temp = 0; temp < 10208; temp += 2) 1214 { 1215 buf[temp] = (byte) ((OFFSET << 2) + (GAIN >> 8)); 1216 buf[temp + 1] = (byte) (GAIN & 0xFF); 1217 } 1218 } 1219 /* Gain/offset table (r,g,b) */ 1220 write_byte (fd, DATAPORT_TARGET, DP_R | DP_OFFSET); 1221 write_word (fd, DATAPORT_ADDR, DP_WRITE); 1222 write_bulk (fd, DATAPORT, buf, 10208); 1223 if (fp) 1224 fread (buf, 2, 5100, fp); 1225 write_byte (fd, DATAPORT_TARGET, DP_G | DP_OFFSET); 1226 write_word (fd, DATAPORT_ADDR, DP_WRITE); 1227 write_bulk (fd, DATAPORT, buf, 10208); 1228 if (fp) 1229 { 1230 fread (buf, 2, 5100, fp); 1231 fclose (fp); 1232 } 1233 write_byte (fd, DATAPORT_TARGET, DP_B | DP_OFFSET); 1234 write_word (fd, DATAPORT_ADDR, DP_WRITE); 1235 write_bulk (fd, DATAPORT, buf, 10208); 1236 1237 free (buf); 1238 return; 1239} 1240 1241 1242/* Scan sequence */ 1243/* resolution is 75,150,300,600,1200 1244 scan coordinates in 600-dpi pixels */ 1245static SANE_Status 1246scan (CANON_Handle * opt) 1247{ 1248 SANE_Status status; 1249 const int left_edge = 0x004b; /* Just for my scanner, or is this 1250 universal? Calibrate? */ 1251 int temp; 1252 int fd = opt->fd; 1253 byte result; 1254 byte *buf; 1255 1256 /* Check status. (not in w2k driver) */ 1257 read_byte (fd, STATUS, &result); /* wants 2f or 2d */ 1258 if (!(result & STATUS_HOME) /*0x2d */ ) 1259 return SANE_STATUS_DEVICE_BUSY; 1260 /* or force it to return? 1261 write_byte(fd, COMMAND, 0x02); 1262 wait_for_return(fd); 1263 */ 1264 1265 /* reserved? */ 1266 read_byte (fd, 0x69, &result); /* wants 0a */ 1267 1268 read_byte (fd, STATUS, &result); /* wants 0e */ 1269 read_byte (fd, PAPER_SENSOR, &result); /* wants 2b */ 1270 write_byte (fd, PAPER_SENSOR, 0x2b); 1271 /* Color mode: 1272 1-Channel Line Rate Color 0x15. 1273 1-Channel Grayscale 0x14 (and we skip some of these tables) */ 1274 write_byte (fd, COLOR_MODE, 0x15); 1275 1276 /* install the offset/gain table */ 1277 install_ogn (fd); 1278 1279 read_byte (fd, STATUS, &result); /* wants 0e */ 1280 /* move forward to "glass 0" */ 1281 write_byte (fd, COMMAND, 0x01); 1282 read_byte (fd, STATUS, &result); /* wants 0c */ 1283 1284 /* create gamma table */ 1285 buf = malloc (0x400); 1286 for (temp = 0; temp < 0x0400; temp++) 1287 /* gamma calculation by M.Reinelt <reinelt@eunet.at> */ 1288 buf[temp] = (double) 255.0 * exp(log((temp + 0.5) / 1023.0) / opt->gamma) 1289 + 0.5; 1290 1291 /* Gamma R, write and verify */ 1292 write_byte (fd, DATAPORT_TARGET, DP_R | DP_GAMMA); 1293 write_word (fd, DATAPORT_ADDR, DP_WRITE); 1294 write_bulk (fd, DATAPORT, buf, 0x0400); 1295 write_byte (fd, DATAPORT_TARGET, DP_R | DP_GAMMA); 1296 write_word (fd, DATAPORT_ADDR, DP_READ); 1297 read_bulk (fd, DATAPORT, buf, 0x0400); 1298 /* Gamma G */ 1299 write_byte (fd, DATAPORT_TARGET, DP_G | DP_GAMMA); 1300 write_word (fd, DATAPORT_ADDR, DP_WRITE); 1301 write_bulk (fd, DATAPORT, buf, 0x0400); 1302 write_byte (fd, DATAPORT_TARGET, DP_G | DP_GAMMA); 1303 write_word (fd, DATAPORT_ADDR, DP_READ); 1304 read_bulk (fd, DATAPORT, buf, 0x0400); 1305 /* Gamma B */ 1306 write_byte (fd, DATAPORT_TARGET, DP_B | DP_GAMMA); 1307 write_word (fd, DATAPORT_ADDR, DP_WRITE); 1308 write_bulk (fd, DATAPORT, buf, 0x0400); 1309 write_byte (fd, DATAPORT_TARGET, DP_B | DP_GAMMA); 1310 write_word (fd, DATAPORT_ADDR, DP_READ); 1311 read_bulk (fd, DATAPORT, buf, 0x0400); 1312 free (buf); 1313 1314 write_byte (fd, CLOCK_DIV, 0x04); 1315 /* Resolution: dpi 75(ie) 100,150(1c) 200,300(1a) 600,1200(18) */ 1316 switch (opt->resolution) 1317 { 1318 case 150: 1319 write_byte (fd, 0x09, 0x1c); 1320 break; 1321 case 300: 1322 write_byte (fd, 0x09, 0x1a); 1323 break; 1324 case 600: 1325 case 1200: 1326 /* actually 600 dpi horiz max */ 1327 write_byte (fd, 0x09, 0x18); 1328 break; 1329 default: /* 75 */ 1330 write_byte (fd, 0x09, 0x1e); 1331 opt->resolution = 75; 1332 } 1333 1334 write_word (fd, ACTIVE_PX_START, left_edge); 1335 /* Data pixel start. Measured at 600dpi regardless of 1336 scan resolution. 0-position is 0x004b */ 1337 write_word (fd, DATA_PX_START, left_edge + opt->x1); 1338 /* Data pixel end. Measured at 600dpi regardless of scan 1339 resolution. */ 1340 write_word (fd, DATA_PX_END, left_edge + opt->x2); 1341 /* greyscale has 14,03, different lights */ 1342 write_byte (fd, COLOR_MODE, 0x15); 1343 write_byte (fd, 0x29, 0x02); 1344 /* Lights */ 1345 write_word (fd, LAMP_R_ON, 0x0017); 1346 /* "Hi-low color" selection from windows driver. low(1437) hi(1481) */ 1347 write_word (fd, LAMP_R_OFF, 0x1437); 1348 write_word (fd, LAMP_G_ON, 0x0017); 1349 write_word (fd, LAMP_G_OFF, 0x094e); 1350 write_word (fd, LAMP_B_ON, 0x0017); 1351 write_word (fd, LAMP_B_OFF, 0x0543); 1352 1353 /* Analog static offset R,G,B. Greyscale has 0,0,0 */ 1354 write_byte (fd, 0x38, 0x3f); 1355 write_byte (fd, 0x39, 0x3f); 1356 write_byte (fd, 0x3a, 0x3f); 1357 /* Analog static gain R,G,B (normally 0x01) */ 1358 write_byte (fd, 0x3b, opt->gain); 1359 write_byte (fd, 0x3c, opt->gain); 1360 write_byte (fd, 0x3d, opt->gain); 1361 /* Digital gain/offset settings. Greyscale has 0 */ 1362 write_byte (fd, 0x3e, 0x1a); 1363 1364 { 1365 /* Stepper motion setup. */ 1366 int stepsize, faststep = 0x0104, reverse = 0x28, phase, pwm = 0x1f; 1367 switch (opt->resolution) 1368 { 1369 case 75: 1370 stepsize = 0x0106; 1371 faststep = 0x0106; 1372 reverse = 0; 1373 phase = 0x39a8; 1374 pwm = 0x3f; 1375 break; 1376 case 150: 1377 stepsize = 0x020d; 1378 phase = 0x3198; 1379 break; 1380 case 300: 1381 stepsize = 0x041a; 1382 phase = 0x2184; 1383 break; 1384 case 600: 1385 stepsize = 0x0835; 1386 phase = 0x0074; 1387 break; 1388 case 1200: 1389 /* 1200 dpi y only, x is 600 dpi */ 1390 stepsize = 0x106b; 1391 phase = 0x41ac; 1392 break; 1393 default: 1394 DBG (1, "BAD RESOLUTION"); 1395 return SANE_STATUS_UNSUPPORTED; 1396 } 1397 1398 write_word (fd, STEP_SIZE, stepsize); 1399 write_word (fd, FAST_STEP, faststep); 1400 /* There sounds like a weird step disjoint at the end of skipsteps 1401 at 75dpi, so I think that's why skipsteps=0 at 75dpi in the 1402 Windows driver. It still works at the normal 0x017a though. */ 1403 /* cal strip is 0x17a steps, plus 2 300dpi microsteps per pixel */ 1404 write_word (fd, SKIP_STEPS, 0x017a /* cal strip */ + opt->y1 * 2); 1405 /* FIXME could be 0x57, why not? */ 1406 write_byte (fd, BUFFER_LIMIT, 0x20); 1407 write_byte (fd, BUFFER_RESUME, 0x02); 1408 write_byte (fd, REVERSE_STEPS, reverse); 1409 /* motor resume phasing */ 1410 write_word (fd, 0x52, phase); 1411 write_byte (fd, STEP_PWM, pwm); 1412 } 1413 1414 read_byte (fd, PAPER_SENSOR, &result); /* wants 2b */ 1415 write_byte (fd, PAPER_SENSOR, 0x0b); 1416 1417 opt->width = (opt->x2 - opt->x1) * opt->resolution / 600 + 1; 1418 opt->height = (opt->y2 - opt->y1) * opt->resolution / 600; 1419 opt->flags = 0; 1420 DBG (1, "width=%d height=%d dpi=%d\n", opt->width, opt->height, 1421 opt->resolution); 1422 CHK (do_scan (opt)); 1423 1424 read_byte (fd, PAPER_SENSOR, &result); /* wants 0b */ 1425 write_byte (fd, PAPER_SENSOR, 0x2b); 1426 write_byte (fd, STEP_PWM, 0x3f); 1427 1428 lights_out (fd); 1429 /* home */ 1430 write_byte (fd, COMMAND, 0x02); 1431 1432 return status; 1433} 1434 1435 1436static SANE_Status 1437CANON_set_scan_parameters (CANON_Handle * scan, 1438 const int forceCal, 1439 const int gray, 1440 const int left, 1441 const int top, 1442 const int right, 1443 const int bottom, 1444 const int res, 1445 const int gain, 1446 const double gamma) 1447{ 1448 DBG (2, "CANON_set_scan_parameters:\n"); 1449 DBG (2, "cal = %d\n", forceCal); 1450 DBG (2, "gray = %d (ignored)\n", gray); 1451 DBG (2, "res = %d\n", res); 1452 DBG (2, "gain = %d\n", gain); 1453 DBG (2, "gamma = %f\n", gamma); 1454 DBG (2, "in 600dpi pixels:\n"); 1455 DBG (2, "left = %d, top = %d\n", left, top); 1456 DBG (2, "right = %d, bottom = %d\n", right, bottom); 1457 1458 /* Validate the input parameters */ 1459 if ((left < 0) || (right > CANON_MAX_WIDTH)) 1460 return SANE_STATUS_INVAL; 1461 1462 if ((top < 0) || (bottom > CANON_MAX_HEIGHT)) 1463 return SANE_STATUS_INVAL; 1464 1465 if (((right - left) < 10) || ((bottom - top) < 10)) 1466 return SANE_STATUS_INVAL; 1467 1468 if ((res != 75) && (res != 150) && (res != 300) 1469 && (res != 600) && (res != 1200)) 1470 return SANE_STATUS_INVAL; 1471 1472 if ((gain < 0) || (gain > 64)) 1473 return SANE_STATUS_INVAL; 1474 1475 if (gamma <= 0.0) 1476 return SANE_STATUS_INVAL; 1477 1478 /* Store params */ 1479 scan->resolution = res; 1480 scan->x1 = left; 1481 scan->x2 = right - /* subtract 1 pixel */ 600 / scan->resolution; 1482 scan->y1 = top; 1483 scan->y2 = bottom; 1484 scan->gain = gain; 1485 scan->gamma = gamma; 1486 scan->flags = forceCal ? FLG_FORCE_CAL : 0; 1487 1488 return SANE_STATUS_GOOD; 1489} 1490 1491 1492static SANE_Status 1493CANON_close_device (CANON_Handle * scan) 1494{ 1495 DBG (3, "CANON_close_device:\n"); 1496 sanei_usb_close (scan->fd); 1497 return SANE_STATUS_GOOD; 1498} 1499 1500 1501static SANE_Status 1502CANON_open_device (CANON_Handle * scan, const char *dev) 1503{ 1504 SANE_Word vendor; 1505 SANE_Word product; 1506 SANE_Status res; 1507 1508 DBG (3, "CANON_open_device: `%s'\n", dev); 1509 1510 scan->fname = NULL; 1511 scan->fp = NULL; 1512 scan->flags = 0; 1513 1514 res = sanei_usb_open (dev, &scan->fd); 1515 if (res != SANE_STATUS_GOOD) 1516 { 1517 DBG (1, "CANON_open_device: couldn't open device `%s': %s\n", dev, 1518 sane_strstatus (res)); 1519 return res; 1520 } 1521 1522#ifndef NO_AUTODETECT 1523 /* We have opened the device. Check that it is a USB scanner. */ 1524 if (sanei_usb_get_vendor_product (scan->fd, &vendor, &product) != 1525 SANE_STATUS_GOOD) 1526 { 1527 DBG (1, "CANON_open_device: sanei_usb_get_vendor_product failed\n"); 1528 /* This is not a USB scanner, or SANE or the OS doesn't support it. */ 1529 sanei_usb_close (scan->fd); 1530 scan->fd = -1; 1531 return SANE_STATUS_UNSUPPORTED; 1532 } 1533 1534 /* Make sure we have a CANON scanner */ 1535 if ((vendor != 0x04a9) || (product != 0x2204)) 1536 { 1537 DBG (1, "CANON_open_device: incorrect vendor/product (0x%x/0x%x)\n", 1538 vendor, product); 1539 sanei_usb_close (scan->fd); 1540 scan->fd = -1; 1541 return SANE_STATUS_UNSUPPORTED; 1542 } 1543#endif 1544 1545 return SANE_STATUS_GOOD; 1546} 1547 1548 1549static const char * 1550CANON_get_device_name (CANON_Handle * scanner) 1551{ 1552 (void) scanner; /* Eliminate warning about unused parameters */ 1553 return "Canoscan FB630U"; 1554} 1555 1556 1557static SANE_Status 1558CANON_finish_scan (CANON_Handle * scanner) 1559{ 1560 DBG (3, "CANON_finish_scan:\n"); 1561 if (scanner->fp) 1562 fclose (scanner->fp); 1563 scanner->fp = NULL; 1564 1565 /* remove temp file */ 1566 if (scanner->fname) 1567 { 1568 DBG (4, "removing temp file %s\n", scanner->fname); 1569 unlink (scanner->fname); 1570 free (scanner->fname); 1571 } 1572 scanner->fname = NULL; 1573 1574 return SANE_STATUS_GOOD; 1575} 1576 1577 1578static SANE_Status 1579CANON_start_scan (CANON_Handle * scanner) 1580{ 1581 int rv; 1582 SANE_Status status; 1583 DBG (3, "CANON_start_scan called\n"); 1584 1585 /* choose a temp file name for scan data */ 1586 scanner->fname = strdup ("/tmp/scan.XXXXXX"); 1587 1588 /* FIXME: we should be using fd, not discarding it! */ 1589 int fd = mkstemp (scanner->fname); 1590 if (fd == -1) 1591 return SANE_STATUS_IO_ERROR; 1592 close(fd); 1593 1594 /* calibrate if needed */ 1595 rv = init (scanner->fd); 1596 if (rv < 0) { 1597 DBG(1, "Can't talk on USB.\n"); 1598 return SANE_STATUS_IO_ERROR; 1599 } 1600 if ((rv == 1) 1601 || !check_ogn_file () 1602 || (scanner->flags & FLG_FORCE_CAL)) { 1603 plugin_cal (scanner); 1604 wait_for_return (scanner->fd); 1605 } 1606 1607 /* scan */ 1608 if ((status = scan (scanner)) != SANE_STATUS_GOOD) 1609 { 1610 CANON_finish_scan (scanner); 1611 return status; 1612 } 1613 1614 /* read the temp file back out */ 1615 scanner->fp = fopen (scanner->fname, "r"); 1616 DBG (4, "reading %s\n", scanner->fname); 1617 if (!scanner->fp) 1618 { 1619 DBG (1, "open %s", scanner->fname); 1620 return SANE_STATUS_IO_ERROR; 1621 } 1622 return SANE_STATUS_GOOD; 1623} 1624 1625 1626static SANE_Status 1627CANON_read (CANON_Handle * scanner, SANE_Byte * data, 1628 SANE_Int max_length, SANE_Int * length) 1629{ 1630 SANE_Status status; 1631 int red_len; 1632 1633 DBG (5, "CANON_read called\n"); 1634 if (!scanner->fp) 1635 return SANE_STATUS_INVAL; 1636 red_len = fread (data, 1, max_length, scanner->fp); 1637 /* return some data */ 1638 if (red_len > 0) 1639 { 1640 *length = red_len; 1641 DBG (5, "CANON_read returned (%d/%d)\n", *length, max_length); 1642 return SANE_STATUS_GOOD; 1643 } 1644 1645 /* EOF or file err */ 1646 *length = 0; 1647 if (feof (scanner->fp)) 1648 { 1649 DBG (4, "EOF\n"); 1650 status = SANE_STATUS_EOF; 1651 } 1652 else 1653 { 1654 DBG (4, "IO ERR\n"); 1655 status = SANE_STATUS_IO_ERROR; 1656 } 1657 1658 CANON_finish_scan (scanner); 1659 DBG (5, "CANON_read returned (%d/%d)\n", *length, max_length); 1660 return status; 1661} 1662