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
76 typedef 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. */
87 typedef 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 }
100 GL640_Request;
101
102 /* Write to the usb-parallel port bridge. */
103 static SANE_Status
gl640WriteControl(int fd,GL640_Request req,byte * data,unsigned int size)104 gl640WriteControl (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. */
122 static SANE_Status
gl640ReadControl(int fd,GL640_Request req,byte * data,unsigned int size)123 gl640ReadControl (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 */
141 static inline SANE_Status
gl640WriteReq(int fd,GL640_Request req,byte data)142 gl640WriteReq (int fd, GL640_Request req, byte data)
143 {
144 return gl640WriteControl (fd, req, &data, 1);
145 }
146
147 static inline SANE_Status
gl640ReadReq(int fd,GL640_Request req,byte * data)148 gl640ReadReq (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 */
160 static SANE_Status
gl640WriteBulk(int fd,byte * setup,byte * data,size_t size)161 gl640WriteBulk (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 */
183 static SANE_Status
gl640ReadBulk(int fd,byte * setup,byte * data,size_t size)184 gl640ReadBulk (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 */
207 static SANE_Status
write_byte(int fd,byte addr,byte val)208 write_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 */
219 static SANE_Status
read_byte(int fd,byte addr,byte * val)220 read_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
230 static byte bulk_setup_data[] = { 0, 0, 0x80, 0, 0, 0, 0, 0 };
231
232 /* Bulk write */
233 static SANE_Status
write_bulk(int fd,unsigned int addr,void * src,size_t count)234 write_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 */
255 static SANE_Status
read_bulk(int fd,unsigned int addr,void * dst,size_t count)256 read_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 */
282 static SANE_Status
write_word(int fd,unsigned int addr,unsigned int data)283 write_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) */
295 static SANE_Status
write_many(int fd,unsigned int addr,const byte * src,size_t count)296 write_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) */
318 static SANE_Status
read_many(int fd,unsigned int addr,void * dst,size_t count)319 read_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 */
344 static int
read_poll_flag(int fd,unsigned int addr,unsigned int mask,unsigned int val)345 read_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 */
372 static int
read_poll_min(int fd,unsigned int addr,unsigned int min)373 read_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. */
400 static int
read_bulk_size(int fd,int ks,int remainder,byte * dest,int destsize)401 read_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
447 typedef 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 }
466 CANON_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
482 static 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,
485 0x4b, /*r20 */ 0x15, 0xe0, /*data px start */ 0x00, 0x4b, /*data px end */ 0x14, 0x37, 0x15, 0x00 };
486
487 static const byte seq003[] =
488 { 0x02, 0x00, 0x00, /*lights out */ 0x03, 0xff, 0x00, 0x01, 0x03, 0xff,
489 0x00, 0x01, 0x03, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06,
490 0x1d, 0x00, 0x13, 0x04, 0x1a, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x57, 0x02, 0x00, 0x3c, 0x35, 0x94,
491 0x00, 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. */
497 static int
init(int fd)498 init (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 */
543 static void
lights_out(int fd)544 lights_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. */
557 static SANE_Status
do_scan(CANON_Handle * s)558 do_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
710 static int
wait_for_return(int fd)711 wait_for_return (int fd)
712 {
713 return read_poll_flag (fd, STATUS, STATUS_HOME, STATUS_HOME);
714 }
715
716
717 static 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 */
725 static int
plugin_cal(CANON_Handle * s)726 plugin_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 mkstemp (s->fname);
941 }
942 s->width = 2551;
943 s->height = 75;
944 s->flags = FLG_PPM_HEADER | FLG_NO_INTERLEAVE;
945 CHK (do_scan (s));
946 compute_ogn (s->fname);
947 unlink (s->fname);
948
949 write_byte (fd, STEP_PWM, 0x3f);
950 /* stepper home */
951 write_byte (fd, COMMAND, 0x02);
952
953 /* discard the remaining data */
954 read_byte (fd, IMAGE_DATA_AVAIL, &result); /* wants 42,4c */
955 if (result > 1)
956 {
957 read_bulk_size (fd, result, 0, 0, 0);
958 DBG (11, "read %dk extra\n", result);
959 }
960 read_byte (fd, 0x69, &result); /* wants 02 */
961 write_byte (fd, 0x69, 0x0a);
962
963 lights_out (fd);
964 init (fd);
965
966 #if 0
967 /* Repeatedly send this every 1 second. Button scan? FIXME */
968 gl640ReadReq (fd, GL640_GPIO_READ, &result); /* wants 00 */
969 #endif
970
971 return 0;
972 }
973
974
975 /* The number of regions in the calibration strip (black & white). */
976 #define NREGIONS 2
977
978 /* Compute the offset/gain table from the calibration strip. This is
979 somewhat more complicated than necessary because I don't hard-code the
980 strip widths; I try to figure out the regions based on the scan data.
981 Theoretically, the region-finder should work for any number of distinct
982 regions (but there are only 2 on this scanner.)
983 This produces the CAL_FILE_OGN file, the final offset/gain table. */
984 static SANE_Status
compute_ogn(char * calfilename)985 compute_ogn (char *calfilename)
986 {
987 byte *linebuf, *oldline, *newline;
988 mode_t oldmask;
989 FILE *fp;
990 int width, height, nlines = 0, region = -1, i, transition = 1, badcnt;
991 int pct;
992 int reglines[NREGIONS];
993 float *avg;
994 float max_range[3], tmp1, tmp2;
995
996 fp = fopen (calfilename, "r");
997 if (!fp)
998 {
999 DBG (1, "open %s\n", calfilename);
1000 return SANE_STATUS_EOF;
1001 }
1002 fscanf (fp, "P6 %d %d %*d ", &width, &height);
1003 DBG (12, "cal file %s %dx%d\n", calfilename, width, height);
1004 width = width * 3; /* 1 byte each of r, g, b */
1005 /* make a buffer holding 2 lines of data */
1006 linebuf = calloc (width * 2, sizeof (linebuf[0]));
1007 /* first line is data read buffer */
1008 newline = linebuf;
1009 /* second line is a temporary holding spot in case the next line read
1010 is the black/white transition, in which case we'll disregard this
1011 one. */
1012 oldline = linebuf + width;
1013 /* column averages per region */
1014 avg = calloc (width * NREGIONS, sizeof (avg[0]));
1015
1016 while (nlines < height)
1017 {
1018 if (fread (newline, 1, width, fp) != (size_t) width)
1019 break;
1020 nlines++;
1021 /* Check if new line is majorly different than old.
1022 Criteria is 10 pixels differing by more than 10%. */
1023 badcnt = 0;
1024 for (i = 0; i < width; i++)
1025 {
1026 pct = newline[i] - oldline[i];
1027 /* Fix by M.Reinelt <reinelt@eunet.at>
1028 * do NOT use 10% (think of a dark area with
1029 * oldline=4 and newline=5, which is a change of 20% !!
1030 * Use an absolute difference of 10 as criteria
1031 */
1032 if (pct < -10 || pct > 10)
1033 {
1034 badcnt++;
1035 DBG (16, "pix%d[%d/%d] ", i, newline[i], oldline[i]);
1036 }
1037 }
1038 DBG (13, "line %d changed %d\n", nlines, badcnt);
1039 if ((badcnt > 10) || (nlines == height))
1040 {
1041 /* End of region. Lines are different or end of data. */
1042 transition++;
1043 if (transition == 1)
1044 DBG (12, "Region %d lines %d-%d\n",
1045 region, nlines - reglines[region], nlines - 1);
1046 }
1047 else
1048 {
1049 /* Lines are similar, so still in region. */
1050 if (transition)
1051 {
1052 /* There was just a transition, so this is the start of a
1053 new region. */
1054 region++;
1055 if (region >= NREGIONS)
1056 /* Too many regions detected. Err below. */
1057 break;
1058 transition = 0;
1059 reglines[region] = 0;
1060 }
1061 /* Add oldline to the current region's average */
1062 for (i = 0; i < width; i++)
1063 avg[i + region * width] += oldline[i];
1064 reglines[region]++;
1065 }
1066 /* And newline becomes old */
1067 memcpy (oldline, newline, width);
1068 }
1069 fclose (fp);
1070 free (linebuf);
1071 region++; /* now call it number of regions instead of index */
1072 DBG (11, "read %d lines as %d regions\n", nlines, region);
1073
1074 /* Check to see if we screwed up */
1075 if (region != NREGIONS)
1076 {
1077 DBG (1, "Warning: gain/offset compute failed.\n"
1078 "Found %d regions instead of %d.\n", region, NREGIONS);
1079 for (i = 0; i < region; i++)
1080 DBG (1, " Region %d: %d lines\n",
1081 i, (i >= NREGIONS) ? -1 : reglines[i]);
1082 free (avg);
1083 return SANE_STATUS_UNSUPPORTED;
1084 }
1085
1086 /* Now we've got regions and sums. Find averages and range. */
1087 max_range[0] = max_range[1] = max_range[2] = 0.0;
1088 for (i = 0; i < width; i++)
1089 {
1090 /* Convert sums to averages */
1091 /* black region */
1092 tmp1 = avg[i] /= reglines[0];
1093 /* white region */
1094 tmp2 = avg[i + width] /= reglines[1];
1095 /* Track largest range for each color.
1096 If image is interleaved, use 'i%3', if not, 'i/(width/3)' */
1097 if ((tmp2 - tmp1) > max_range[i / (width / 3)])
1098 {
1099 max_range[i / (width / 3)] = tmp2 - tmp1;
1100 DBG (14, "max %d@%d %f-%f=%f\n",
1101 i / (width / 3), i, tmp2, tmp1, tmp2 - tmp1);
1102 }
1103 }
1104 DBG (13, "max range r %f\n", max_range[0]);
1105 DBG (13, "max range g %f\n", max_range[1]);
1106 DBG (13, "max range b %f\n", max_range[2]);
1107
1108 /* Set umask to world r/w so other users can overwrite common cal... */
1109 oldmask = umask (0);
1110 fp = fopen (CAL_FILE_OGN, "w");
1111 /* ... and set it back. */
1112 umask (oldmask);
1113 if (!fp)
1114 {
1115 DBG (1, "open " CAL_FILE_OGN);
1116 free (avg);
1117 return SANE_STATUS_IO_ERROR;
1118 }
1119
1120 /* Finally, compute offset and gain */
1121 for (i = 0; i < width; i++)
1122 {
1123 int gain, offset;
1124 byte ogn[2];
1125
1126 /* skip line termination flags */
1127 if (!((i + 1) % (width / 3)))
1128 {
1129 DBG (13, "skip scanline EOL %d/%d\n", i, width);
1130 continue;
1131 }
1132
1133 /* Gain multiplier:
1134 255 : 1.5 times brighter
1135 511 : 2 times brighter
1136 1023: 3 times brighter */
1137 #if 1
1138 /* Original gain/offset */
1139 gain = 512 * ((max_range[i / (width / 3)] /
1140 (avg[i + width] - avg[i])) - 1);
1141 offset = avg[i];
1142 #else
1143 /* This doesn't work for some people. For instance, a negative
1144 offset would be bad. */
1145
1146 /* Enhanced offset and gain calculation by M.Reinelt <reinelt@eunet.at>
1147 * These expressions were found by an iterative calibration process,
1148 * by changing gain and offset values for every pixel until the desired
1149 * values for black and white were reached, and finding an approximation
1150 * formula.
1151 * Note that offset is linear, but gain isn't!
1152 */
1153 offset = (double)3.53 * avg[i] - 125;
1154 gain = (double)3861.0 * exp(-0.0168 * (avg[i + width] - avg[i]));
1155 #endif
1156
1157 DBG (14, "%d wht=%f blk=%f diff=%f gain=%d offset=%d\n", i,
1158 avg[i + width], avg[i], avg[i + width] - avg[i], gain, offset);
1159 /* 10-bit gain, 6-bit offset (subtractor) in two bytes */
1160 ogn[0] = (byte) (((offset << 2) + (gain >> 8)) & 0xFF);
1161 ogn[1] = (byte) (gain & 0xFF);
1162 fwrite (ogn, sizeof (byte), 2, fp);
1163 /* Annoyingly, we seem to use ogn data at 600dpi, while we scanned
1164 at 300, so double our file. Much easier than doubling at the
1165 read. */
1166 fwrite (ogn, sizeof (byte), 2, fp);
1167 }
1168
1169 fclose (fp);
1170 free (avg);
1171 return SANE_STATUS_GOOD;
1172 }
1173
1174 static int
check_ogn_file(void)1175 check_ogn_file (void)
1176 {
1177 FILE *fp;
1178 fp = fopen (CAL_FILE_OGN, "r");
1179 if (fp)
1180 {
1181 fclose (fp);
1182 return 1;
1183 }
1184 return 0;
1185 }
1186
1187 /* Load or fake the offset/gain table */
1188 static void
install_ogn(int fd)1189 install_ogn (int fd)
1190 {
1191 int temp;
1192 byte *buf;
1193 FILE *fp;
1194
1195 /* 8.5in at 600dpi = 5104 pixels in scan head
1196 10-bit gain + 6-bit offset = 2 bytes per pixel, so 10208 bytes */
1197 buf = malloc (10208);
1198
1199 fp = fopen (CAL_FILE_OGN, "r");
1200 if (fp)
1201 {
1202 fread (buf, 2, 5100, fp);
1203 /* screw the last 4 pixels */
1204 }
1205 else
1206 {
1207 /* Make up the gain/offset data. */
1208 #define GAIN 256 /* 1.5x */
1209 #define OFFSET 0
1210 for (temp = 0; temp < 10208; temp += 2)
1211 {
1212 buf[temp] = (byte) ((OFFSET << 2) + (GAIN >> 8));
1213 buf[temp + 1] = (byte) (GAIN & 0xFF);
1214 }
1215 }
1216 /* Gain/offset table (r,g,b) */
1217 write_byte (fd, DATAPORT_TARGET, DP_R | DP_OFFSET);
1218 write_word (fd, DATAPORT_ADDR, DP_WRITE);
1219 write_bulk (fd, DATAPORT, buf, 10208);
1220 if (fp)
1221 fread (buf, 2, 5100, fp);
1222 write_byte (fd, DATAPORT_TARGET, DP_G | DP_OFFSET);
1223 write_word (fd, DATAPORT_ADDR, DP_WRITE);
1224 write_bulk (fd, DATAPORT, buf, 10208);
1225 if (fp)
1226 {
1227 fread (buf, 2, 5100, fp);
1228 fclose (fp);
1229 }
1230 write_byte (fd, DATAPORT_TARGET, DP_B | DP_OFFSET);
1231 write_word (fd, DATAPORT_ADDR, DP_WRITE);
1232 write_bulk (fd, DATAPORT, buf, 10208);
1233
1234 free (buf);
1235 return;
1236 }
1237
1238
1239 /* Scan sequence */
1240 /* resolution is 75,150,300,600,1200
1241 scan coordinates in 600-dpi pixels */
1242 static SANE_Status
scan(CANON_Handle * opt)1243 scan (CANON_Handle * opt)
1244 {
1245 SANE_Status status;
1246 const int left_edge = 0x004b; /* Just for my scanner, or is this
1247 universal? Calibrate? */
1248 int temp;
1249 int fd = opt->fd;
1250 byte result;
1251 byte *buf;
1252
1253 /* Check status. (not in w2k driver) */
1254 read_byte (fd, STATUS, &result); /* wants 2f or 2d */
1255 if (!(result & STATUS_HOME) /*0x2d */ )
1256 return SANE_STATUS_DEVICE_BUSY;
1257 /* or force it to return?
1258 write_byte(fd, COMMAND, 0x02);
1259 wait_for_return(fd);
1260 */
1261
1262 /* reserved? */
1263 read_byte (fd, 0x69, &result); /* wants 0a */
1264
1265 read_byte (fd, STATUS, &result); /* wants 0e */
1266 read_byte (fd, PAPER_SENSOR, &result); /* wants 2b */
1267 write_byte (fd, PAPER_SENSOR, 0x2b);
1268 /* Color mode:
1269 1-Channel Line Rate Color 0x15.
1270 1-Channel Grayscale 0x14 (and we skip some of these tables) */
1271 write_byte (fd, COLOR_MODE, 0x15);
1272
1273 /* install the offset/gain table */
1274 install_ogn (fd);
1275
1276 read_byte (fd, STATUS, &result); /* wants 0e */
1277 /* move forward to "glass 0" */
1278 write_byte (fd, COMMAND, 0x01);
1279 read_byte (fd, STATUS, &result); /* wants 0c */
1280
1281 /* create gamma table */
1282 buf = malloc (0x400);
1283 for (temp = 0; temp < 0x0400; temp++)
1284 /* gamma calculation by M.Reinelt <reinelt@eunet.at> */
1285 buf[temp] = (double) 255.0 * exp(log((temp + 0.5) / 1023.0) / opt->gamma)
1286 + 0.5;
1287
1288 /* Gamma R, write and verify */
1289 write_byte (fd, DATAPORT_TARGET, DP_R | DP_GAMMA);
1290 write_word (fd, DATAPORT_ADDR, DP_WRITE);
1291 write_bulk (fd, DATAPORT, buf, 0x0400);
1292 write_byte (fd, DATAPORT_TARGET, DP_R | DP_GAMMA);
1293 write_word (fd, DATAPORT_ADDR, DP_READ);
1294 read_bulk (fd, DATAPORT, buf, 0x0400);
1295 /* Gamma G */
1296 write_byte (fd, DATAPORT_TARGET, DP_G | DP_GAMMA);
1297 write_word (fd, DATAPORT_ADDR, DP_WRITE);
1298 write_bulk (fd, DATAPORT, buf, 0x0400);
1299 write_byte (fd, DATAPORT_TARGET, DP_G | DP_GAMMA);
1300 write_word (fd, DATAPORT_ADDR, DP_READ);
1301 read_bulk (fd, DATAPORT, buf, 0x0400);
1302 /* Gamma B */
1303 write_byte (fd, DATAPORT_TARGET, DP_B | DP_GAMMA);
1304 write_word (fd, DATAPORT_ADDR, DP_WRITE);
1305 write_bulk (fd, DATAPORT, buf, 0x0400);
1306 write_byte (fd, DATAPORT_TARGET, DP_B | DP_GAMMA);
1307 write_word (fd, DATAPORT_ADDR, DP_READ);
1308 read_bulk (fd, DATAPORT, buf, 0x0400);
1309 free (buf);
1310
1311 write_byte (fd, CLOCK_DIV, 0x04);
1312 /* Resolution: dpi 75(ie) 100,150(1c) 200,300(1a) 600,1200(18) */
1313 switch (opt->resolution)
1314 {
1315 case 150:
1316 write_byte (fd, 0x09, 0x1c);
1317 break;
1318 case 300:
1319 write_byte (fd, 0x09, 0x1a);
1320 break;
1321 case 600:
1322 case 1200:
1323 /* actually 600 dpi horiz max */
1324 write_byte (fd, 0x09, 0x18);
1325 break;
1326 default: /* 75 */
1327 write_byte (fd, 0x09, 0x1e);
1328 opt->resolution = 75;
1329 }
1330
1331 write_word (fd, ACTIVE_PX_START, left_edge);
1332 /* Data pixel start. Measured at 600dpi regardless of
1333 scan resolution. 0-position is 0x004b */
1334 write_word (fd, DATA_PX_START, left_edge + opt->x1);
1335 /* Data pixel end. Measured at 600dpi regardless of scan
1336 resolution. */
1337 write_word (fd, DATA_PX_END, left_edge + opt->x2);
1338 /* greyscale has 14,03, different lights */
1339 write_byte (fd, COLOR_MODE, 0x15);
1340 write_byte (fd, 0x29, 0x02);
1341 /* Lights */
1342 write_word (fd, LAMP_R_ON, 0x0017);
1343 /* "Hi-low color" selection from windows driver. low(1437) hi(1481) */
1344 write_word (fd, LAMP_R_OFF, 0x1437);
1345 write_word (fd, LAMP_G_ON, 0x0017);
1346 write_word (fd, LAMP_G_OFF, 0x094e);
1347 write_word (fd, LAMP_B_ON, 0x0017);
1348 write_word (fd, LAMP_B_OFF, 0x0543);
1349
1350 /* Analog static offset R,G,B. Greyscale has 0,0,0 */
1351 write_byte (fd, 0x38, 0x3f);
1352 write_byte (fd, 0x39, 0x3f);
1353 write_byte (fd, 0x3a, 0x3f);
1354 /* Analog static gain R,G,B (normally 0x01) */
1355 write_byte (fd, 0x3b, opt->gain);
1356 write_byte (fd, 0x3c, opt->gain);
1357 write_byte (fd, 0x3d, opt->gain);
1358 /* Digital gain/offset settings. Greyscale has 0 */
1359 write_byte (fd, 0x3e, 0x1a);
1360
1361 {
1362 /* Stepper motion setup. */
1363 int stepsize, faststep = 0x0104, reverse = 0x28, phase, pwm = 0x1f;
1364 switch (opt->resolution)
1365 {
1366 case 75:
1367 stepsize = 0x0106;
1368 faststep = 0x0106;
1369 reverse = 0;
1370 phase = 0x39a8;
1371 pwm = 0x3f;
1372 break;
1373 case 150:
1374 stepsize = 0x020d;
1375 phase = 0x3198;
1376 break;
1377 case 300:
1378 stepsize = 0x041a;
1379 phase = 0x2184;
1380 break;
1381 case 600:
1382 stepsize = 0x0835;
1383 phase = 0x0074;
1384 break;
1385 case 1200:
1386 /* 1200 dpi y only, x is 600 dpi */
1387 stepsize = 0x106b;
1388 phase = 0x41ac;
1389 break;
1390 default:
1391 DBG (1, "BAD RESOLUTION");
1392 return SANE_STATUS_UNSUPPORTED;
1393 }
1394
1395 write_word (fd, STEP_SIZE, stepsize);
1396 write_word (fd, FAST_STEP, faststep);
1397 /* There sounds like a weird step disjoint at the end of skipsteps
1398 at 75dpi, so I think that's why skipsteps=0 at 75dpi in the
1399 Windows driver. It still works at the normal 0x017a though. */
1400 /* cal strip is 0x17a steps, plus 2 300dpi microsteps per pixel */
1401 write_word (fd, SKIP_STEPS, 0x017a /* cal strip */ + opt->y1 * 2);
1402 /* FIXME could be 0x57, why not? */
1403 write_byte (fd, BUFFER_LIMIT, 0x20);
1404 write_byte (fd, BUFFER_RESUME, 0x02);
1405 write_byte (fd, REVERSE_STEPS, reverse);
1406 /* motor resume phasing */
1407 write_word (fd, 0x52, phase);
1408 write_byte (fd, STEP_PWM, pwm);
1409 }
1410
1411 read_byte (fd, PAPER_SENSOR, &result); /* wants 2b */
1412 write_byte (fd, PAPER_SENSOR, 0x0b);
1413
1414 opt->width = (opt->x2 - opt->x1) * opt->resolution / 600 + 1;
1415 opt->height = (opt->y2 - opt->y1) * opt->resolution / 600;
1416 opt->flags = 0;
1417 DBG (1, "width=%d height=%d dpi=%d\n", opt->width, opt->height,
1418 opt->resolution);
1419 CHK (do_scan (opt));
1420
1421 read_byte (fd, PAPER_SENSOR, &result); /* wants 0b */
1422 write_byte (fd, PAPER_SENSOR, 0x2b);
1423 write_byte (fd, STEP_PWM, 0x3f);
1424
1425 lights_out (fd);
1426 /* home */
1427 write_byte (fd, COMMAND, 0x02);
1428
1429 return status;
1430 }
1431
1432
1433 static SANE_Status
CANON_set_scan_parameters(CANON_Handle * scan,const int forceCal,const int gray,const int left,const int top,const int right,const int bottom,const int res,const int gain,const double gamma)1434 CANON_set_scan_parameters (CANON_Handle * scan,
1435 const int forceCal,
1436 const int gray,
1437 const int left,
1438 const int top,
1439 const int right,
1440 const int bottom,
1441 const int res,
1442 const int gain,
1443 const double gamma)
1444 {
1445 DBG (2, "CANON_set_scan_parameters:\n");
1446 DBG (2, "cal = %d\n", forceCal);
1447 DBG (2, "gray = %d (ignored)\n", gray);
1448 DBG (2, "res = %d\n", res);
1449 DBG (2, "gain = %d\n", gain);
1450 DBG (2, "gamma = %f\n", gamma);
1451 DBG (2, "in 600dpi pixels:\n");
1452 DBG (2, "left = %d, top = %d\n", left, top);
1453 DBG (2, "right = %d, bottom = %d\n", right, bottom);
1454
1455 /* Validate the input parameters */
1456 if ((left < 0) || (right > CANON_MAX_WIDTH))
1457 return SANE_STATUS_INVAL;
1458
1459 if ((top < 0) || (bottom > CANON_MAX_HEIGHT))
1460 return SANE_STATUS_INVAL;
1461
1462 if (((right - left) < 10) || ((bottom - top) < 10))
1463 return SANE_STATUS_INVAL;
1464
1465 if ((res != 75) && (res != 150) && (res != 300)
1466 && (res != 600) && (res != 1200))
1467 return SANE_STATUS_INVAL;
1468
1469 if ((gain < 0) || (gain > 64))
1470 return SANE_STATUS_INVAL;
1471
1472 if (gamma <= 0.0)
1473 return SANE_STATUS_INVAL;
1474
1475 /* Store params */
1476 scan->resolution = res;
1477 scan->x1 = left;
1478 scan->x2 = right - /* subtract 1 pixel */ 600 / scan->resolution;
1479 scan->y1 = top;
1480 scan->y2 = bottom;
1481 scan->gain = gain;
1482 scan->gamma = gamma;
1483 scan->flags = forceCal ? FLG_FORCE_CAL : 0;
1484
1485 return SANE_STATUS_GOOD;
1486 }
1487
1488
1489 static SANE_Status
CANON_close_device(CANON_Handle * scan)1490 CANON_close_device (CANON_Handle * scan)
1491 {
1492 DBG (3, "CANON_close_device:\n");
1493 sanei_usb_close (scan->fd);
1494 return SANE_STATUS_GOOD;
1495 }
1496
1497
1498 static SANE_Status
CANON_open_device(CANON_Handle * scan,const char * dev)1499 CANON_open_device (CANON_Handle * scan, const char *dev)
1500 {
1501 SANE_Word vendor;
1502 SANE_Word product;
1503 SANE_Status res;
1504
1505 DBG (3, "CANON_open_device: `%s'\n", dev);
1506
1507 scan->fname = NULL;
1508 scan->fp = NULL;
1509 scan->flags = 0;
1510
1511 res = sanei_usb_open (dev, &scan->fd);
1512 if (res != SANE_STATUS_GOOD)
1513 {
1514 DBG (1, "CANON_open_device: couldn't open device `%s': %s\n", dev,
1515 sane_strstatus (res));
1516 return res;
1517 }
1518
1519 #ifndef NO_AUTODETECT
1520 /* We have opened the device. Check that it is a USB scanner. */
1521 if (sanei_usb_get_vendor_product (scan->fd, &vendor, &product) !=
1522 SANE_STATUS_GOOD)
1523 {
1524 DBG (1, "CANON_open_device: sanei_usb_get_vendor_product failed\n");
1525 /* This is not a USB scanner, or SANE or the OS doesn't support it. */
1526 sanei_usb_close (scan->fd);
1527 scan->fd = -1;
1528 return SANE_STATUS_UNSUPPORTED;
1529 }
1530
1531 /* Make sure we have a CANON scanner */
1532 if ((vendor != 0x04a9) || (product != 0x2204))
1533 {
1534 DBG (1, "CANON_open_device: incorrect vendor/product (0x%x/0x%x)\n",
1535 vendor, product);
1536 sanei_usb_close (scan->fd);
1537 scan->fd = -1;
1538 return SANE_STATUS_UNSUPPORTED;
1539 }
1540 #endif
1541
1542 return SANE_STATUS_GOOD;
1543 }
1544
1545
1546 static const char *
CANON_get_device_name(CANON_Handle * scanner)1547 CANON_get_device_name (CANON_Handle * scanner)
1548 {
1549 scanner = scanner; /* Eliminate warning about unused parameters */
1550 return "Canoscan FB630U";
1551 }
1552
1553
1554 static SANE_Status
CANON_finish_scan(CANON_Handle * scanner)1555 CANON_finish_scan (CANON_Handle * scanner)
1556 {
1557 DBG (3, "CANON_finish_scan:\n");
1558 if (scanner->fp)
1559 fclose (scanner->fp);
1560 scanner->fp = NULL;
1561
1562 /* remove temp file */
1563 if (scanner->fname)
1564 {
1565 DBG (4, "removing temp file %s\n", scanner->fname);
1566 unlink (scanner->fname);
1567 free (scanner->fname);
1568 }
1569 scanner->fname = NULL;
1570
1571 return SANE_STATUS_GOOD;
1572 }
1573
1574
1575 static SANE_Status
CANON_start_scan(CANON_Handle * scanner)1576 CANON_start_scan (CANON_Handle * scanner)
1577 {
1578 int rv;
1579 SANE_Status status;
1580 DBG (3, "CANON_start_scan called\n");
1581
1582 /* choose a temp file name for scan data */
1583 scanner->fname = strdup ("/tmp/scan.XXXXXX");
1584 if (!mkstemp (scanner->fname))
1585 return SANE_STATUS_IO_ERROR;
1586
1587 /* calibrate if needed */
1588 rv = init (scanner->fd);
1589 if (rv < 0) {
1590 DBG(1, "Can't talk on USB.\n");
1591 return SANE_STATUS_IO_ERROR;
1592 }
1593 if ((rv == 1)
1594 || !check_ogn_file ()
1595 || (scanner->flags & FLG_FORCE_CAL)) {
1596 plugin_cal (scanner);
1597 wait_for_return (scanner->fd);
1598 }
1599
1600 /* scan */
1601 if ((status = scan (scanner)) != SANE_STATUS_GOOD)
1602 {
1603 CANON_finish_scan (scanner);
1604 return status;
1605 }
1606
1607 /* read the temp file back out */
1608 scanner->fp = fopen (scanner->fname, "r");
1609 DBG (4, "reading %s\n", scanner->fname);
1610 if (!scanner->fp)
1611 {
1612 DBG (1, "open %s", scanner->fname);
1613 return SANE_STATUS_IO_ERROR;
1614 }
1615 return SANE_STATUS_GOOD;
1616 }
1617
1618
1619 static SANE_Status
CANON_read(CANON_Handle * scanner,SANE_Byte * data,SANE_Int max_length,SANE_Int * length)1620 CANON_read (CANON_Handle * scanner, SANE_Byte * data,
1621 SANE_Int max_length, SANE_Int * length)
1622 {
1623 SANE_Status status;
1624 int red_len;
1625
1626 DBG (5, "CANON_read called\n");
1627 if (!scanner->fp)
1628 return SANE_STATUS_INVAL;
1629 red_len = fread (data, 1, max_length, scanner->fp);
1630 /* return some data */
1631 if (red_len > 0)
1632 {
1633 *length = red_len;
1634 DBG (5, "CANON_read returned (%d/%d)\n", *length, max_length);
1635 return SANE_STATUS_GOOD;
1636 }
1637
1638 /* EOF or file err */
1639 *length = 0;
1640 if (feof (scanner->fp))
1641 {
1642 DBG (4, "EOF\n");
1643 status = SANE_STATUS_EOF;
1644 }
1645 else
1646 {
1647 DBG (4, "IO ERR\n");
1648 status = SANE_STATUS_IO_ERROR;
1649 }
1650
1651 CANON_finish_scan (scanner);
1652 DBG (5, "CANON_read returned (%d/%d)\n", *length, max_length);
1653 return status;
1654 }
1655