1 /**
2 * Description of the Primax PagePartner model
3 */
4 static P5_Model pagepartner_model = {
5 "Primax PagePartner",
6 "Primax",
7 "PagePartner",
8 SANE_I18N ("sheetfed scanner"),
9
10 {300, 200, 150, 100, 0},
11 /* 500 seems also possible */
12 {600, 400, 300, 200, 150, 100, 0},
13
14 300,
15 600,
16 100,
17 100,
18 16,
19
20 SANE_FIX (0.0),
21 SANE_FIX (0.0),
22 SANE_FIX (215.9),
23 SANE_FIX (300.0),
24 };
25
26 #ifdef HAVE_LINUX_PPDEV_H
27 static char *
addr_name(uint16_t addr)28 addr_name (uint16_t addr)
29 {
30 switch (addr)
31 {
32 case DATA:
33 return "DATA";
34 break;
35 case STATUS:
36 return "STATUS";
37 break;
38 case CONTROL:
39 return "CONTROL";
40 break;
41 case EPPADR:
42 return "EPPADR";
43 break;
44 case EPPDATA:
45 return "EPPDATA";
46 break;
47 default:
48 return "*ERROR*";
49 }
50 }
51 #endif
52
53 /** @brief low level hardware access functions
54 * @{
55 */
56
57 static uint8_t
p5_inb(int fd, uint16_t addr)58 p5_inb (int fd, uint16_t addr)
59 {
60 #ifdef HAVE_LINUX_PPDEV_H
61 uint8_t val = 0xff;
62 int rc, mode = 0xff;
63
64 switch (addr)
65 {
66 case DATA:
67 rc = ioctl (fd, PPRDATA, &val);
68 break;
69 case STATUS:
70 rc = ioctl (fd, PPRSTATUS, &val);
71 break;
72 case CONTROL:
73 rc = ioctl (fd, PPRCONTROL, &val);
74 break;
75 case EPPDATA:
76 mode = 1; /* data_reverse */
77 rc = ioctl (fd, PPDATADIR, &mode);
78 mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
79 rc = ioctl (fd, PPSETMODE, &mode);
80 #ifdef PPSETFLAGS
81 mode = PP_FASTREAD;
82 rc = ioctl (fd, PPSETFLAGS, &mode);
83 #endif
84 rc = read (fd, &val, 1);
85 break;
86 default:
87 DBG (DBG_error, "p5_inb(%s) escaped ppdev\n", addr_name (addr));
88 return 0xFF;
89 }
90 if (rc < 0)
91 {
92 DBG (DBG_error, "ppdev ioctl returned <%s>\n", strerror (errno));
93 }
94 return val;
95 #else
96 if(fd && addr)
97 return 0;
98 return 0;
99 #endif
100 }
101
102 static void
p5_outb(int fd, uint16_t addr, uint8_t value)103 p5_outb (int fd, uint16_t addr, uint8_t value)
104 {
105 #ifdef HAVE_LINUX_PPDEV_H
106 int rc = 0, mode = 0xff;
107
108 switch (addr)
109 {
110 case DATA:
111 rc = ioctl (fd, PPWDATA, &value);
112 break;
113 case CONTROL:
114 mode = value & 0x20;
115 rc = ioctl (fd, PPDATADIR, &mode);
116 if (!rc)
117 {
118 value = value & 0xDF;
119 rc = ioctl (fd, PPWCONTROL, &value);
120 }
121 break;
122 case EPPDATA:
123 mode = 0; /* data forward */
124 rc = ioctl (fd, PPDATADIR, &mode);
125 mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
126 rc = ioctl (fd, PPSETMODE, &mode);
127 rc = write (fd, &value, 1);
128 break;
129 case EPPADR:
130 mode = 0; /* data forward */
131 rc = ioctl (fd, PPDATADIR, &mode);
132 mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
133 rc = ioctl (fd, PPSETMODE, &mode);
134 rc = write (fd, &value, 1);
135 break;
136 default:
137 DBG (DBG_error, "p5_outb(%s,0x%02x) escaped ppdev\n", addr_name (addr),
138 value);
139 break;
140 }
141 if (rc < 0)
142 {
143 DBG (DBG_error, "ppdev ioctl returned <%s>\n", strerror (errno));
144 }
145 #else
146 if(fd && addr && value)
147 return;
148 #endif /* HAVE_LINUX_PPDEV_H */
149 }
150
151 static void
write_reg(int fd, uint8_t index, uint8_t value)152 write_reg (int fd, uint8_t index, uint8_t value)
153 {
154 uint8_t idx;
155
156 /* both nibbles hold the same value */
157 idx = index & 0x0F;
158 DBG (DBG_io2, "write_reg(REG%X,0x%x)\n", idx, value);
159 idx = idx << 4 | idx;
160 p5_outb (fd, EPPADR, idx);
161 p5_outb (fd, EPPDATA, value);
162 }
163
164 static uint8_t
read_reg(int fd, uint8_t index)165 read_reg (int fd, uint8_t index)
166 {
167 uint8_t idx;
168
169 /* both nibbles hold the same value */
170 idx = index & 0x0F;
171 idx = idx << 4 | idx;
172 p5_outb (fd, EPPADR, idx);
173 return p5_inb (fd, EPPDATA);
174 }
175
176 #ifdef HAVE_LINUX_PPDEV_H
177 static int
read_data(int fd, uint8_t * data, int length)178 read_data (int fd, uint8_t * data, int length)
179 {
180 int mode, rc, nb;
181 unsigned char bval;
182
183 bval = REG8;
184 mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
185 rc = ioctl (fd, PPSETMODE, &mode);
186 rc = write (fd, &bval, 1);
187
188 mode = 1; /* data_reverse */
189 rc = ioctl (fd, PPDATADIR, &mode);
190 #ifdef PPSETFLAGS
191 mode = PP_FASTREAD;
192 rc = ioctl (fd, PPSETFLAGS, &mode);
193 #endif
194 mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
195 rc = ioctl (fd, PPSETMODE, &mode);
196 nb = 0;
197 while (nb < length)
198 {
199 rc = read (fd, data + nb, length - nb);
200 if (rc < 0)
201 {
202 DBG (DBG_error, "memtest: error reading data back!\n");
203 return 0;
204 }
205 else
206 {
207 nb += rc;
208 }
209 }
210
211 return 1;
212 }
213
214 static void
index_write_data(int fd, uint8_t index, uint8_t * data, int length)215 index_write_data (int fd, uint8_t index, uint8_t * data, int length)
216 {
217 int mode;
218 unsigned char bval;
219
220 bval = index;
221 mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
222 ioctl (fd, PPSETMODE, &mode);
223 write (fd, &bval, 1);
224
225 mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
226 ioctl (fd, PPSETMODE, &mode);
227 mode = 0; /* data forward */
228 ioctl (fd, PPDATADIR, &mode);
229 write (fd, data, length);
230 return;
231 }
232
233 static void
write_data(int fd, uint8_t * data, int length)234 write_data (int fd, uint8_t * data, int length)
235 {
236 index_write_data (fd, REG8, data, length);
237 }
238
239 static void
write_reg2(int fd, uint8_t index, uint16_t value)240 write_reg2 (int fd, uint8_t index, uint16_t value)
241 {
242 uint8_t data2[2];
243
244 data2[0] = value & 0xff;
245 data2[1] = value >> 8;
246 index_write_data (fd, index, data2, 2);
247 }
248 #else
249
250 static int
read_data(int fd, uint8_t * data, int length)251 read_data (int fd, uint8_t * data, int length)
252 {
253 if(fd && data && length)
254 return -1;
255 return -1;
256 }
257
258 static void
write_data(int fd, uint8_t * data, int length)259 write_data (int fd, uint8_t * data, int length)
260 {
261 if(fd && data && length)
262 return;
263 }
264
265 static void
write_reg2(int fd, uint8_t index, uint16_t value)266 write_reg2 (int fd, uint8_t index, uint16_t value)
267 {
268 if(fd && index && value)
269 return;
270 }
271 #endif
272
273 /**
274 * @}
275 */
276
277
278 /** @brief This function checks a memory buffer.
279 * This function writes at the given memory address then read it back
280 * to check the scanner is correctly working.
281 * @param fd file descriptor used to access hardware
282 * @param addr address where to write and read
283 * @return SANE_TRUE on success, SANE_FALSE otherwise
284 */
285 static int
memtest(int fd, uint16_t addr)286 memtest (int fd, uint16_t addr)
287 {
288 uint8_t sent[256];
289 uint8_t back[256];
290 int i;
291
292 write_reg2 (fd, REG1, addr);
293 for (i = 0; i < 256; i++)
294 {
295 sent[i] = (uint8_t) i;
296 back[i] = 0;
297 }
298 write_data (fd, sent, 256);
299 read_data (fd, back, 256);
300
301 /* check if data read back is the same that the one sent */
302 for (i = 0; i < 256; i++)
303 {
304 if (back[i] != sent[i])
305 {
306 return SANE_FALSE;
307 }
308 }
309
310 return SANE_TRUE;
311 }
312
313
314 #define P5_INB(k,y,z) val=p5_inb(k,y); if(val!=z) { DBG(DBG_error,"expected 0x%02x, got 0x%02x\n",z, val); return SANE_FALSE; }
315
316 /** @brief connect to scanner
317 * This function sends the connect sequence for the scanner.
318 * @param fd filedescriptor of the parallel port communication channel
319 * @return SANE_TRUE in case of success, SANE_FALSE otherwise
320 */
321 static int
connect(int fd)322 connect (int fd)
323 {
324 uint8_t val;
325
326 p5_inb (fd, CONTROL);
327 p5_outb (fd, CONTROL, 0x04);
328 p5_outb (fd, DATA, 0x02);
329 P5_INB (fd, DATA, 0x02);
330 p5_outb (fd, DATA, 0x03);
331 P5_INB (fd, DATA, 0x03);
332 p5_outb (fd, DATA, 0x03);
333 p5_outb (fd, DATA, 0x83);
334 p5_outb (fd, DATA, 0x03);
335 p5_outb (fd, DATA, 0x83);
336 P5_INB (fd, DATA, 0x83);
337 p5_outb (fd, DATA, 0x82);
338 P5_INB (fd, DATA, 0x82);
339 p5_outb (fd, DATA, 0x02);
340 p5_outb (fd, DATA, 0x82);
341 p5_outb (fd, DATA, 0x02);
342 p5_outb (fd, DATA, 0x82);
343 P5_INB (fd, DATA, 0x82);
344 p5_outb (fd, DATA, 0x82);
345 P5_INB (fd, DATA, 0x82);
346 p5_outb (fd, DATA, 0x02);
347 p5_outb (fd, DATA, 0x82);
348 p5_outb (fd, DATA, 0x02);
349 p5_outb (fd, DATA, 0x82);
350 P5_INB (fd, DATA, 0x82);
351 p5_outb (fd, DATA, 0x83);
352 P5_INB (fd, DATA, 0x83);
353 p5_outb (fd, DATA, 0x03);
354 p5_outb (fd, DATA, 0x83);
355 p5_outb (fd, DATA, 0x03);
356 p5_outb (fd, DATA, 0x83);
357 P5_INB (fd, DATA, 0x83);
358 p5_outb (fd, DATA, 0x82);
359 P5_INB (fd, DATA, 0x82);
360 p5_outb (fd, DATA, 0x02);
361 p5_outb (fd, DATA, 0x82);
362 p5_outb (fd, DATA, 0x02);
363 p5_outb (fd, DATA, 0x82);
364 P5_INB (fd, DATA, 0x82);
365 p5_outb (fd, DATA, 0x83);
366 P5_INB (fd, DATA, 0x83);
367 p5_outb (fd, DATA, 0x03);
368 p5_outb (fd, DATA, 0x83);
369 p5_outb (fd, DATA, 0x03);
370 p5_outb (fd, DATA, 0x83);
371 P5_INB (fd, DATA, 0x83);
372 p5_outb (fd, DATA, 0x83);
373 P5_INB (fd, DATA, 0x83);
374 p5_outb (fd, DATA, 0x03);
375 p5_outb (fd, DATA, 0x83);
376 p5_outb (fd, DATA, 0x03);
377 p5_outb (fd, DATA, 0x83);
378 P5_INB (fd, DATA, 0x83);
379 p5_outb (fd, DATA, 0x82);
380 P5_INB (fd, DATA, 0x82);
381 p5_outb (fd, DATA, 0x02);
382 p5_outb (fd, DATA, 0x82);
383 p5_outb (fd, DATA, 0x02);
384 p5_outb (fd, DATA, 0x82);
385 p5_outb (fd, DATA, 0xFF);
386 DBG (DBG_info, "connect() OK...\n");
387 return SANE_TRUE;
388 }
389
390 static int
disconnect(int fd)391 disconnect (int fd)
392 {
393 uint8_t val;
394
395 p5_outb (fd, CONTROL, 0x04);
396 p5_outb (fd, DATA, 0x00);
397 P5_INB (fd, DATA, 0x00);
398 p5_outb (fd, DATA, 0x01);
399 P5_INB (fd, DATA, 0x01);
400 p5_outb (fd, DATA, 0x01);
401 p5_outb (fd, DATA, 0x81);
402 p5_outb (fd, DATA, 0x01);
403 p5_outb (fd, DATA, 0x81);
404 P5_INB (fd, DATA, 0x81);
405 p5_outb (fd, DATA, 0x80);
406 P5_INB (fd, DATA, 0x80);
407 p5_outb (fd, DATA, 0x00);
408 p5_outb (fd, DATA, 0x80);
409 p5_outb (fd, DATA, 0x00);
410 p5_outb (fd, DATA, 0x80);
411 P5_INB (fd, DATA, 0x80);
412 p5_outb (fd, DATA, 0x80);
413 P5_INB (fd, DATA, 0x80);
414 p5_outb (fd, DATA, 0x00);
415 p5_outb (fd, DATA, 0x80);
416 p5_outb (fd, DATA, 0x00);
417 p5_outb (fd, DATA, 0x80);
418 P5_INB (fd, DATA, 0x80);
419 p5_outb (fd, DATA, 0x81);
420 P5_INB (fd, DATA, 0x81);
421 p5_outb (fd, DATA, 0x01);
422 p5_outb (fd, DATA, 0x81);
423 p5_outb (fd, DATA, 0x01);
424 p5_outb (fd, DATA, 0x81);
425 P5_INB (fd, DATA, 0x81);
426 p5_outb (fd, DATA, 0x80);
427 P5_INB (fd, DATA, 0x80);
428 p5_outb (fd, DATA, 0x00);
429 p5_outb (fd, DATA, 0x80);
430 p5_outb (fd, DATA, 0x00);
431 p5_outb (fd, DATA, 0x80);
432 P5_INB (fd, DATA, 0x80);
433 p5_outb (fd, DATA, 0x00);
434 p5_outb (fd, DATA, 0x80);
435 p5_outb (fd, DATA, 0x00);
436 p5_outb (fd, DATA, 0x80);
437 P5_INB (fd, DATA, 0x80);
438 p5_outb (fd, DATA, 0x00);
439 p5_outb (fd, DATA, 0x80);
440 p5_outb (fd, DATA, 0x00);
441 p5_outb (fd, DATA, 0x80);
442 P5_INB (fd, DATA, 0x80);
443 p5_outb (fd, DATA, 0x00);
444 p5_outb (fd, DATA, 0x80);
445 p5_outb (fd, DATA, 0x00);
446 p5_outb (fd, DATA, 0x80);
447 p5_inb (fd, CONTROL);
448 p5_outb (fd, CONTROL, 0x0C);
449
450 return SANE_STATUS_GOOD;
451 }
452
453 static void
setadresses(int fd, uint16_t start, uint16_t end)454 setadresses (int fd, uint16_t start, uint16_t end)
455 {
456 write_reg (fd, REG3, start & 0xff);
457 write_reg (fd, REG4, start >> 8);
458 write_reg (fd, REG5, end & 0xff);
459 write_reg (fd, REG6, end >> 8);
460 DBG (DBG_io, "setadresses(0x%x,0x%x); OK...\n", start, end);
461 }
462
463 #ifdef HAVE_LINUX_PPDEV_H
464 /** @brief open parallel port device
465 * opens parallel port's low level device in EPP mode
466 * @param devicename nam of the real device or the special value 'auto'
467 * @return file descriptor in cas of successn -1 otherwise
468 */
469 static int
open_pp(const char *devicename)470 open_pp (const char *devicename)
471 {
472 int fd, mode = 0;
473 char *name;
474
475 DBG (DBG_proc, "open_pp: start, devicename=%s\n", devicename);
476 /* TODO improve auto device finding */
477 if (strncmp (devicename, "auto", 4) == 0)
478 {
479 name = strdup("/dev/parport0");
480 }
481 else
482 {
483 name = strdup(devicename);
484 }
485
486 /* open device */
487 fd = open (name, O_RDWR);
488 if (fd < 0)
489 {
490 switch (errno)
491 {
492 case ENOENT:
493 #ifdef ENIO
494 case ENXIO:
495 #endif
496 #ifdef ENODEV
497 case ENODEV:
498 #endif
499 DBG (DBG_error, "open_pp: no %s device ...\n", name);
500 break;
501 case EACCES:
502 DBG (DBG_error,
503 "open_pp: current user cannot use existing %s device ...\n",
504 name);
505 break;
506 default:
507 DBG (DBG_error, "open_pp: %s while opening %s\n", strerror (errno),
508 name);
509 }
510 return -1;
511 }
512 free(name);
513
514 /* claim device and set it to EPP */
515 ioctl (fd, PPCLAIM);
516 ioctl (fd, PPGETMODES, &mode);
517 if (mode & PARPORT_MODE_PCSPP)
518 DBG (DBG_io, "PARPORT_MODE_PCSPP\n");
519 if (mode & PARPORT_MODE_TRISTATE)
520 DBG (DBG_io, "PARPORT_MODE_TRISTATE\n");
521 if (mode & PARPORT_MODE_EPP)
522 DBG (DBG_io, "PARPORT_MODE_EPP\n");
523 if (mode & PARPORT_MODE_ECP)
524 DBG (DBG_io, "PARPORT_MODE_ECP\n");
525 if (mode & PARPORT_MODE_COMPAT)
526 DBG (DBG_io, "PARPORT_MODE_COMPAT\n");
527 if (mode & PARPORT_MODE_DMA)
528 DBG (DBG_io, "PARPORT_MODE_DMA\n");
529 if (mode & PARPORT_MODE_EPP)
530 {
531 mode = IEEE1284_MODE_EPP;
532 }
533 else
534 {
535 /*
536 if (mode & PARPORT_MODE_ECP)
537 {
538 mode = IEEE1284_MODE_ECP;
539 }
540 else
541 */
542 {
543 mode = -1;
544 }
545 }
546 if (mode == -1)
547 {
548 DBG (DBG_error, "open_pp: no EPP mode, giving up ...\n");
549 ioctl (fd, PPRELEASE);
550 close (fd);
551 return -1;
552 }
553 ioctl (fd, PPNEGOT, &mode);
554 ioctl (fd, PPSETMODE, &mode);
555 DBG (DBG_proc, "open_pp: exit\n");
556 return fd;
557 }
558
559 /** close low level device
560 * release and close low level hardware device
561 */
562 static void
close_pp(int fd)563 close_pp (int fd)
564 {
565 int mode = IEEE1284_MODE_COMPAT;
566
567 if (fd > 2)
568 {
569 ioctl (fd, PPNEGOT, &mode);
570 ioctl (fd, PPRELEASE);
571 close (fd);
572 }
573 }
574
575 #else /* HAVE_LINUX_PPDEV_H */
576
577 static int
open_pp(const char *devicename)578 open_pp (const char *devicename)
579 {
580 if(devicename)
581 return -1;
582 return -1;
583 }
584
585 static void
close_pp(int fd)586 close_pp (int fd)
587 {
588 if(fd)
589 return;
590 }
591 #endif /* HAVE_LINUX_PPDEV_H */
592
593 /** @brief test if a document is inserted
594 * Test if a document is inserted by reading register E
595 * @param fd file descriptor to access scanner
596 * @return SANE_STATUS_NO_DOCS if no document or SANE_STATUS_GOOD
597 * if something is present.
598 */
599 static SANE_Status
test_document(int fd)600 test_document (int fd)
601 {
602 int detector;
603
604 /* check for document presence 0xC6: present, 0xC3 no document */
605 detector = read_reg (fd, REGE);
606 DBG (DBG_io, "test_document: detector=0x%02X\n", detector);
607
608 /* document inserted */
609 if (detector & 0x04)
610 return SANE_STATUS_GOOD;
611
612 return SANE_STATUS_NO_DOCS;
613 }
614
615 /**
616 * return the amount of scanned data available
617 * @param fd file descriptor to access scanner
618 * @return available byte number
619 */
620 static int
available_bytes(int fd)621 available_bytes (int fd)
622 {
623 int counter;
624
625 /* read the number of 256 bytes block of scanned data */
626 counter = read_reg (fd, REG9);
627 DBG (DBG_io, "available_bytes: available_bytes=0x%02X\n", counter);
628 return 256 * counter;
629 }
630
631 static SANE_Status
build_correction(P5_Device * dev, unsigned int dpi, unsigned int mode, unsigned int start, unsigned int width)632 build_correction (P5_Device * dev, unsigned int dpi, unsigned int mode,
633 unsigned int start, unsigned int width)
634 {
635 unsigned int i, j, shift, step;
636
637 DBG (DBG_proc, "build_correction: start=%d, width=%d\n", start, width);
638 DBG (DBG_trace, "build_correction: dpi=%d, mode=%d\n", dpi, mode);
639
640 /* loop on calibration data to find the matching one */
641 j = 0;
642 while (dev->calibration_data[j]->dpi != dpi)
643 {
644 j++;
645 if (j > MAX_RESOLUTIONS)
646 {
647 DBG (DBG_error, "build_correction: couldn't find calibration!\n");
648 return SANE_STATUS_INVAL;
649 }
650 }
651
652 if (dev->gain != NULL)
653 {
654 free (dev->gain);
655 dev->gain = NULL;
656 }
657 if (dev->offset != NULL)
658 {
659 free (dev->offset);
660 dev->offset = NULL;
661 }
662 dev->gain = (float *) malloc (width * sizeof (float));
663 if (dev->gain == NULL)
664 {
665 DBG (DBG_error,
666 "build_correction: failed to allocate memory for gain!\n");
667 return SANE_STATUS_NO_MEM;
668 }
669 dev->offset = (uint8_t *) malloc (width);
670 if (dev->offset == NULL)
671 {
672 DBG (DBG_error,
673 "build_correction: failed to allocate memory for offset!\n");
674 return SANE_STATUS_NO_MEM;
675 }
676
677 /* compute starting point of calibration data to use */
678 shift = start;
679 step = 1;
680 if (mode == MODE_GRAY)
681 {
682 /* we use green data */
683 shift += 1;
684 step = 3;
685 }
686 for (i = 0; i < width; i += step)
687 {
688 if (dev->calibration_data[j]->white_data[shift + i] -
689 dev->calibration_data[0]->black_data[shift + i] > BLACK_LEVEL)
690 {
691 dev->gain[i] =
692 WHITE_TARGET /
693 ((float)
694 (dev->calibration_data[j]->white_data[shift + i] -
695 dev->calibration_data[j]->black_data[shift + i]));
696 dev->offset[i] = dev->calibration_data[j]->black_data[shift + i];
697 }
698 else
699 {
700 dev->gain[i] = 1.0;
701 dev->offset[i] = 0;
702 }
703 }
704 return SANE_STATUS_GOOD;
705 DBG (DBG_proc, "build_correction: end\n");
706 }
707
708 /** @brief start up a real scan
709 * This function starts the scan with the given parameters.
710 * @param dev device describing hardware
711 * @param mode color, gray level or lineart.
712 * @param dpi desired scan resolution.
713 * @param startx coordinate of the first pixel to scan in
714 * scan's resolution coordinate
715 * @param width width of the scanned area
716 * scanner's physical scan aread.
717 * @return SANE_STATUS_GOOD if scan is successfully started
718 */
719 static SANE_Status
start_scan(P5_Device * dev, int mode, unsigned int dpi, unsigned int startx, unsigned int width)720 start_scan (P5_Device * dev, int mode, unsigned int dpi, unsigned int startx,
721 unsigned int width)
722 {
723 uint8_t reg0=0;
724 uint8_t reg2=0;
725 uint8_t regF=0;
726 uint16_t addr=0;
727 uint16_t start, end;
728 unsigned int xdpi;
729
730 DBG (DBG_proc, "start_scan: start \n");
731 DBG (DBG_io, "start_scan: startx=%d, width=%d, dpi=%d\n", startx, width,
732 dpi);
733
734 /** @brief register values
735 * - reg2 : reg2 seems related to x dpi and provides only 100,
736 * 150, 200 and 300 resolutions.
737 * - regF : lower nibble gives y dpi resolution ranging from 150
738 * to 1200 dpi.
739 */
740 xdpi = dpi;
741 switch (dpi)
742 {
743 case 100:
744 reg2 = 0x90;
745 regF = 0xA2;
746 break;
747 case 150:
748 reg2 = 0x10;
749 regF = 0xA4;
750 break;
751 case 200:
752 reg2 = 0x80;
753 regF = 0xA6;
754 break;
755 case 300:
756 reg2 = 0x00;
757 regF = 0xA8;
758 break;
759 case 400:
760 reg2 = 0x80; /* xdpi=200 */
761 regF = 0xAA;
762 xdpi = 200;
763 break;
764 case 500:
765 reg2 = 0x00;
766 regF = 0xAC;
767 xdpi = 300;
768 break;
769 case 600:
770 reg2 = 0x00;
771 regF = 0xAE;
772 xdpi = 300;
773 break;
774 }
775
776 switch (mode)
777 {
778 case MODE_COLOR:
779 reg0 = 0x00;
780 addr = 0x0100;
781 break;
782 case MODE_GRAY:
783 /* green channel only */
784 reg0 = 0x20;
785 addr = 0x0100;
786 break;
787 case MODE_LINEART:
788 reg0 = 0x40;
789 addr = 0x0908;
790 break;
791 }
792
793 write_reg (dev->fd, REG1, 0x01);
794 write_reg (dev->fd, REG7, 0x00);
795 write_reg (dev->fd, REG0, reg0);
796 write_reg (dev->fd, REG1, 0x00);
797 write_reg (dev->fd, REGF, regF);
798 /* the memory addr used to test need not to be related
799 * to resolution, 0x0100 could be always used */
800 /* TODO get rid of it */
801 memtest (dev->fd, addr);
802
803 /* handle case where dpi>xdpi */
804 start = startx;
805 if (dpi > xdpi)
806 {
807 width = (width * xdpi) / dpi;
808 start = (startx * xdpi) / dpi;
809 }
810
811 /* compute and set start addr */
812 if (mode == MODE_COLOR)
813 {
814 start = start * 3;
815 width = width * 3;
816 }
817 end = start + width + 1;
818
819 /* build calibration data for the scan */
820 if (dev->calibrated)
821 {
822 build_correction (dev, xdpi, mode, start, width);
823 }
824
825 setadresses (dev->fd, start, end);
826
827 write_reg (dev->fd, REG1, addr >> 8);
828 write_reg (dev->fd, REG2, reg2);
829 regF = (regF & 0x0F) | 0x80;
830 write_reg (dev->fd, REGF, regF);
831 write_reg (dev->fd, REG0, reg0);
832 if (mode == MODE_LINEART)
833 {
834 write_reg (dev->fd, 0x07, 0x04);
835 }
836 else
837 {
838 write_reg (dev->fd, 0x07, 0x00);
839 }
840 write_reg (dev->fd, REG1, addr >> 8);
841 write_reg2 (dev->fd, REG1, addr);
842 write_reg (dev->fd, REGF, regF | 0x01);
843 write_reg (dev->fd, REG0, reg0 | 0x0C);
844 if (mode == MODE_LINEART)
845 {
846 write_reg (dev->fd, REG1, 0x19);
847 }
848 else
849 {
850 write_reg (dev->fd, REG1, 0x11);
851 }
852 DBG (DBG_proc, "start_scan: exit\n");
853 return SANE_STATUS_GOOD;
854 }
855
856 /** read a line of scan data
857 * @param dev device to read
858 * @param data pointer where to store data
859 * @param length total bytes to read on one line
860 * @param ltr total number of lines to read
861 * @param retry signals that the function must read as much lines it can
862 * @param x2 tells that lines must be enlarged by a 2 factor
863 * @param mode COLOR_MODE if color mode
864 * @returns number of data lines read, -1 in case of error
865 */
866 static int
read_line(P5_Device * dev, uint8_t * data, size_t length, int ltr, SANE_Bool retry, SANE_Bool x2, int mode, SANE_Bool correction)867 read_line (P5_Device * dev, uint8_t * data, size_t length, int ltr,
868 SANE_Bool retry, SANE_Bool x2, int mode, SANE_Bool correction)
869 {
870 uint8_t counter, read, cnt;
871 uint8_t inbuffer[MAX_SENSOR_PIXELS * 2 * 3 + 2];
872 unsigned int i, factor;
873 float val;
874
875 DBG (DBG_proc, "read_line: trying to read %d lines of %lu bytes\n", ltr,
876 (unsigned long)length);
877
878 counter = read_reg (dev->fd, REG9);
879 DBG (DBG_io, "read_line: %d bytes available\n", counter * 256);
880 read = 0;
881 if (x2 == SANE_FALSE)
882 {
883 factor = 1;
884 }
885 else
886 {
887 factor = 2;
888 }
889
890 /* in retry mode we read until not enough data, but in no retry
891 * read only one line , counter give us 256 bytes block available
892 * and we want an number multiple of color channels */
893 cnt = (255 + length / factor) / 256;
894 while ((counter > cnt && retry == 1) || (counter > cnt && read == 0))
895 {
896 /* read data from scanner, first and last byte aren't picture data */
897 read_data (dev->fd, inbuffer, length / factor + 2);
898
899 /* image correction */
900 if (correction == SANE_TRUE)
901 {
902 for (i = 0; i < length / factor; i++)
903 {
904 val = inbuffer[i + 1] - dev->offset[i];
905 if (val > 0)
906 {
907 val = val * dev->gain[i];
908 if (val < 255)
909 inbuffer[i + 1] = val;
910 else
911 inbuffer[i + 1] = 255;
912 }
913 else
914 {
915 inbuffer[i + 1] = 0;
916 }
917 }
918 }
919
920 /* handle horizontal data doubling */
921 if (x2 == SANE_FALSE)
922 {
923 memcpy (data + read * length, inbuffer + 1, length);
924 }
925 else
926 {
927 if (mode == MODE_COLOR)
928 {
929 for (i = 0; i < length / factor; i += 3)
930 {
931 data[read * length + i * factor] = inbuffer[i + 1];
932 data[read * length + i * factor + 1] = inbuffer[i + 2];
933 data[read * length + i * factor + 2] = inbuffer[i + 3];
934 data[read * length + i * factor + 3] = inbuffer[i + 1];
935 data[read * length + i * factor + 4] = inbuffer[i + 2];
936 data[read * length + i * factor + 5] = inbuffer[i + 3];
937 }
938 }
939 else
940 {
941 for (i = 0; i < length / factor; i++)
942 {
943 data[read * length + i * factor] = inbuffer[i + 1];
944 data[read * length + i * factor + 1] = inbuffer[i + 1];
945 }
946 }
947 }
948 read++;
949 if (retry == SANE_TRUE)
950 {
951 read_reg (dev->fd, REGF);
952 read_reg (dev->fd, REGA);
953 read_reg (dev->fd, REG9);
954 counter = read_reg (dev->fd, REG9);
955 read_reg (dev->fd, REGA);
956 if (read >= ltr)
957 {
958 DBG (DBG_io, "read_line returning %d lines\n", read);
959 return read;
960 }
961 counter = read_reg (dev->fd, REG9);
962 }
963 }
964 read_reg (dev->fd, REGF);
965 read_reg (dev->fd, REGA);
966 read_reg (dev->fd, REG9);
967 counter = read_reg (dev->fd, REG9);
968 read_reg (dev->fd, REGA);
969 DBG (DBG_io, "read_line returning %d lines\n", read);
970 return read;
971 }
972
973
974 static SANE_Status
eject(int fd)975 eject (int fd)
976 {
977 int detector;
978
979 DBG (DBG_proc, "eject: start ...\n");
980
981 do
982 {
983 write_reg2 (fd, REG1, 0x1110);
984 detector = read_reg (fd, REGE);
985 detector = read_reg (fd, REGE);
986 }
987 while ((detector & 0x04) != 0);
988 write_reg (fd, REG0, 0x00);
989 write_reg (fd, REG1, 0x00);
990 write_reg (fd, REGF, 0x82);
991 write_reg (fd, REG7, 0x00);
992
993 DBG (DBG_proc, "eject: end.\n");
994 return SANE_STATUS_GOOD;
995 }
996
997 /** @brief wait for document to be present in feeder
998 * Polls document sensor until something is present. Give up after 20 seconds
999 * @param fd file descriptor of the physical device
1000 */
1001 /* static int
1002 wait_document (int fd, uint8_t detector)
1003 {
1004 int count = 0;
1005 uint8_t val;
1006
1007 write_reg (fd, REG1, 0x00);
1008 write_reg (fd, REG7, 0x00);
1009 detector = read_reg (fd, REGE);
1010 while (detector == 0xc3 && count < 20)
1011 {
1012 sleep (1);
1013 count++;
1014 detector = read_reg (fd, REGE);
1015 }
1016 setadresses (fd, 0x002d, 0x09c7);
1017 write_reg (fd, REG1, 0x00);
1018 write_reg (fd, REG2, 0x90);
1019 write_reg (fd, REGF, 0x82);
1020 write_reg (fd, REG0, 0x00);
1021 val = p5_inb (fd, STATUS) & 0xf8;
1022 if (val != 0xf8)
1023 {
1024 DBG (DBG_error, "wait_document: unexpected STATUS value 0x%02x instead of 0xf8", val);
1025 }
1026 if (count >= 20)
1027 {
1028 DBG (DBG_error, "wait_document: failed to detect document!\n");
1029 return 0;
1030 }
1031 return 1;
1032 } */
1033
1034 /** @brief move at 150 dpi
1035 * move the paper at 150 dpi motor speed by the amount specified
1036 * @params dev pointer to the device structure
1037 */
1038 static SANE_Status
move(P5_Device * dev)1039 move (P5_Device * dev)
1040 {
1041 int skip, done, read, count;
1042 SANE_Status status = SANE_STATUS_GOOD;
1043 unsigned char buffer[256];
1044
1045 DBG (DBG_proc, "move: start\n");
1046
1047 /* compute number of lines to skip */
1048 skip = dev->ystart;
1049
1050 /* works, but remains to be explained ... */
1051 if (dev->ydpi > 300)
1052 skip = skip / 2;
1053
1054 DBG (DBG_io, "move: skipping %d lines at %d dpi\n", skip, dev->ydpi);
1055
1056 /* we do a real scan of small width, discarding data */
1057 done = 0;
1058 status = start_scan (dev, MODE_GRAY, dev->ydpi, 0, 256);
1059 if (status != SANE_STATUS_GOOD)
1060 {
1061 DBG (DBG_error, "move: failed to start scan\n");
1062 return SANE_STATUS_INVAL;
1063 }
1064
1065 do
1066 {
1067 /* test if document left the feeder */
1068 status = test_document (dev->fd);
1069 if (status == SANE_STATUS_NO_DOCS)
1070 {
1071 DBG (DBG_info,
1072 "move: document was shorter than the required move\n");
1073 return SANE_STATUS_INVAL;
1074 }
1075 /* test if data is available */
1076 count = available_bytes (dev->fd);
1077 if (count)
1078 {
1079 read =
1080 read_line (dev, buffer, 256, 1, SANE_FALSE, SANE_FALSE,
1081 MODE_GRAY, SANE_FALSE);
1082 if (read == -1)
1083 {
1084 DBG (DBG_error, "move: failed to read data\n");
1085 return SANE_STATUS_INVAL;
1086 }
1087 done += read;
1088 }
1089 }
1090 while (done < skip);
1091
1092 /* reset scanner */
1093 write_reg2 (dev->fd, REG1, 0x1110);
1094 count = read_reg (dev->fd, REGE);
1095 count = read_reg (dev->fd, REGE);
1096 write_reg (dev->fd, REG0, 0x00);
1097 write_reg (dev->fd, REG1, 0x00);
1098 write_reg (dev->fd, REGF, 0x82);
1099 write_reg (dev->fd, REG7, 0x00);
1100
1101 DBG (DBG_proc, "move: exit\n");
1102 return status;
1103 }
1104
1105 /** clean up calibration data
1106 * @param dev device to clean up
1107 */
1108 static void
cleanup_calibration(P5_Device * dev)1109 cleanup_calibration (P5_Device * dev)
1110 {
1111 int i;
1112
1113 for (i = 0; i < MAX_RESOLUTIONS * 2; i++)
1114 {
1115 if (dev->calibration_data[i] != NULL)
1116 {
1117 free (dev->calibration_data[i]);
1118 dev->calibration_data[i] = NULL;
1119 }
1120 }
1121 dev->calibrated = SANE_FALSE;
1122 }
1123
1124 /** detect a black scan line
1125 * parses the given buffer and return SANE_TRUE if the line is an
1126 * acceptable black line for calibration
1127 * @param buffer data line to parse
1128 * @param pixels number of pixels
1129 * @param mode MODE_COLOR or MODE_GRAY
1130 * @returns SANE_TRUE if it is considered as a white line
1131 */
1132 static SANE_Bool
is_black_line(uint8_t * buffer, unsigned int pixels, int mode)1133 is_black_line (uint8_t * buffer, unsigned int pixels, int mode)
1134 {
1135 unsigned int i, start, end, count, width;
1136
1137 /* compute width in bytes */
1138 if (mode == MODE_COLOR)
1139 {
1140 width = pixels * 3;
1141 }
1142 else
1143 {
1144 width = pixels;
1145 }
1146
1147 /* we allow the calibration target to be narrower than full width, ie
1148 * black margin at both ends of the line */
1149 start = (5 * width) / 100;
1150 end = (95 * width) / 100;
1151 count = 0;
1152
1153 /* count number of black bytes */
1154 for (i = start; i < end; i++)
1155 {
1156 if (buffer[i] > BLACK_LEVEL)
1157 {
1158 count++;
1159 }
1160 }
1161
1162 /* we allow 3% black pixels maximum */
1163 if (count > (3 * width) / 100)
1164 {
1165 DBG (DBG_io, "is_black_line=SANE_FALSE\n");
1166 return SANE_FALSE;
1167 }
1168
1169 DBG (DBG_io, "is_black_line=SANE_TRUE\n");
1170 return SANE_TRUE;
1171 }
1172
1173 /** detect a white scan line
1174 * parses the given buffer and return SANE_TRUE if the line is an
1175 * acceptable white line for calibration
1176 * @param buffer data line to parse
1177 * @param pixels number of pixels
1178 * @param mode MODE_COLOR or MODE_GRAY
1179 * @returns SANE_TRUE if it is considered as a white line
1180 */
1181 static SANE_Bool
is_white_line(uint8_t * buffer, unsigned int pixels, int mode)1182 is_white_line (uint8_t * buffer, unsigned int pixels, int mode)
1183 {
1184 unsigned int i, start, end, count, width;
1185
1186 /* compute width in bytes */
1187 if (mode == MODE_COLOR)
1188 {
1189 width = pixels * 3;
1190 }
1191 else
1192 {
1193 width = pixels;
1194 }
1195
1196 /* we allow the calibration target to be narrower than full width, ie
1197 * black margin at both ends of the line */
1198 start = (5 * width) / 100;
1199 end = (95 * width) / 100;
1200 count = 0;
1201
1202 /* count number of black bytes */
1203 for (i = start; i < end; i++)
1204 {
1205 if (buffer[i] < BLACK_LEVEL)
1206 {
1207 count++;
1208 }
1209 }
1210
1211 /* we allow 3% black pixels maximum */
1212 if (count > (3 * width) / 100)
1213 {
1214 DBG (DBG_io, "is_white_line=SANE_FALSE\n");
1215 return SANE_FALSE;
1216 }
1217
1218 DBG (DBG_io, "is_white_line=SANE_TRUE\n");
1219 return SANE_TRUE;
1220 }
1221
1222 /* ------------------------------------------------------------------------- */
1223 /* writes gray data to a pnm file */
1224 /*
1225 static void
1226 write_gray_data (unsigned char *image, char *name, SANE_Int width,
1227 SANE_Int height)
1228 {
1229 FILE *fdbg = NULL;
1230
1231 fdbg = fopen (name, "wb");
1232 if (fdbg == NULL)
1233 return;
1234 fprintf (fdbg, "P5\n%d %d\n255\n", width, height);
1235 fwrite (image, width, height, fdbg);
1236 fclose (fdbg);
1237 }
1238 */
1239
1240 /* ------------------------------------------------------------------------- */
1241 /* writes rgb data to a pnm file */
1242 static void
write_rgb_data(char *name, unsigned char *image, SANE_Int width, SANE_Int height)1243 write_rgb_data (char *name, unsigned char *image, SANE_Int width,
1244 SANE_Int height)
1245 {
1246 FILE *fdbg = NULL;
1247
1248 fdbg = fopen (name, "wb");
1249 if (fdbg == NULL)
1250 return;
1251 fprintf (fdbg, "P6\n%d %d\n255\n", width, height);
1252 fwrite (image, width * 3, height, fdbg);
1253 fclose (fdbg);
1254 }
1255
1256 /** give calibration file name
1257 * computes the calibration file name to use based on the
1258 * backend name and device
1259 */
1260 static char *
calibration_file(const char *devicename)1261 calibration_file (const char *devicename)
1262 {
1263 char *ptr = NULL;
1264 char tmp_str[PATH_MAX];
1265
1266 ptr = getenv ("HOME");
1267 if (ptr != NULL)
1268 {
1269 sprintf (tmp_str, "%s/.sane/p5-%s.cal", ptr, devicename);
1270 }
1271 else
1272 {
1273 ptr = getenv ("TMPDIR");
1274 if (ptr != NULL)
1275 {
1276 sprintf (tmp_str, "%s/p5-%s.cal", ptr, devicename);
1277 }
1278 else
1279 {
1280 sprintf (tmp_str, "/tmp/p5-%s.cal", devicename);
1281 }
1282 }
1283 DBG (DBG_trace, "calibration_file: using >%s< for calibration file name\n",
1284 tmp_str);
1285 return strdup (tmp_str);
1286 }
1287
1288 /** restore calibration data
1289 * restore calibration data by loading previously saved calibration data
1290 * @param dev device to restore
1291 * @return SANE_STATUS_GOOD on success, otherwise error code
1292 */
1293 static SANE_Status
restore_calibration(P5_Device * dev)1294 restore_calibration (P5_Device * dev)
1295 {
1296 SANE_Status status = SANE_STATUS_GOOD;
1297 char *fname = NULL;
1298 FILE *fcalib = NULL;
1299 size_t size;
1300 int i;
1301
1302 DBG (DBG_proc, "restore_calibration: start\n");
1303 cleanup_calibration (dev);
1304 fname = calibration_file (dev->model->name);
1305 fcalib = fopen (fname, "rb");
1306 if (fcalib == NULL)
1307 {
1308 DBG (DBG_error, "restore_calibration: failed to open %s!\n", fname);
1309 free (fname);
1310 return SANE_STATUS_IO_ERROR;
1311 }
1312
1313 /* loop filling calibration data until EOF reached */
1314 i = 0;
1315 while (!feof (fcalib) && (i < 2 * MAX_RESOLUTIONS))
1316 {
1317 dev->calibration_data[i] = malloc (sizeof (P5_Calibration_Data));
1318 if (dev->calibration_data[i] == NULL)
1319 {
1320 cleanup_calibration (dev);
1321 free (fname);
1322 fclose (fcalib);
1323 DBG (DBG_error,
1324 "restore_calibration: failed to allocate memory for calibration\n");
1325 return SANE_STATUS_NO_MEM;
1326 }
1327 size =
1328 fread (dev->calibration_data[i], 1, sizeof (P5_Calibration_Data),
1329 fcalib);
1330 if (feof (fcalib))
1331 {
1332 free (dev->calibration_data[i]);
1333 dev->calibration_data[i] = NULL;
1334 }
1335 else if (size != sizeof (P5_Calibration_Data))
1336 {
1337 cleanup_calibration (dev);
1338 free (fname);
1339 fclose (fcalib);
1340 DBG (DBG_error, "restore_calibration: failed to read from file\n");
1341 return SANE_STATUS_IO_ERROR;
1342 }
1343 DBG (DBG_trace,
1344 "restore_calibration: read 1 calibration structure from file\n");
1345 i++;
1346 }
1347
1348 dev->calibrated = SANE_TRUE;
1349 fclose (fcalib);
1350 free (fname);
1351
1352 DBG (DBG_proc, "restore_calibration: end\n");
1353 return status;
1354 }
1355
1356 /** save calibration data
1357 * save calibration data from memory to file
1358 * @param dev device calibration to save
1359 * @return SANE_STATUS_GOOD on success, otherwise error code
1360 */
1361 static SANE_Status
save_calibration(P5_Device * dev)1362 save_calibration (P5_Device * dev)
1363 {
1364 SANE_Status status = SANE_STATUS_GOOD;
1365 char *fname = NULL;
1366 FILE *fcalib = NULL;
1367 int i;
1368 size_t size;
1369
1370 DBG (DBG_proc, "save_calibration: start\n");
1371 fname = calibration_file (dev->model->name);
1372 fcalib = fopen (fname, "wb");
1373 if (fcalib == NULL)
1374 {
1375 DBG (DBG_error, "save_calibration: failed to open %s!\n", fname);
1376 free (fname);
1377 return SANE_STATUS_IO_ERROR;
1378 }
1379
1380 /* loop filling calibration data until EOF reached */
1381 i = 0;
1382 while (dev->calibration_data[i] != NULL && (i < 2 * MAX_RESOLUTIONS))
1383 {
1384 size =
1385 fwrite (dev->calibration_data[i], sizeof (P5_Calibration_Data), 1,
1386 fcalib);
1387 if (size != sizeof (P5_Calibration_Data))
1388 {
1389 free (fname);
1390 fclose (fcalib);
1391 DBG (DBG_error, "save_calibration: failed to write to file\n");
1392 return SANE_STATUS_IO_ERROR;
1393 }
1394 DBG (DBG_trace,
1395 "save_calibration: wrote 1 calibration structure to file\n");
1396 i++;
1397 }
1398
1399 fclose (fcalib);
1400 free (fname);
1401
1402 DBG (DBG_proc, "save_calibration: end\n");
1403 return status;
1404 }
1405
1406 /** calibrate scanner
1407 * calibrates scanner by scanning a white sheet to get
1408 * reference data. The black reference data is extracted from the lines
1409 * that precede the physical document.
1410 * Calibration is done at 300 color, then data is built for other modes
1411 * and resolutions.
1412 * @param dev device to calibrate
1413 */
1414 static SANE_Status
sheetfed_calibration(P5_Device * dev)1415 sheetfed_calibration (P5_Device * dev)
1416 {
1417 uint8_t buffer[MAX_SENSOR_PIXELS * 3];
1418 uint16_t white_data[MAX_SENSOR_PIXELS * 3];
1419 uint16_t black_data[MAX_SENSOR_PIXELS * 3];
1420 unsigned int i, j, k, dpi, pixels, read, black, white;
1421 float coeff;
1422 unsigned int red, green, blue;
1423 int line;
1424 SANE_Status status;
1425 char title[40];
1426
1427 FILE *dbg = fopen ("debug.pnm", "wb");
1428 fprintf (dbg, "P6\n%d %d\n255\n", MAX_SENSOR_PIXELS,
1429 CALIBRATION_SKIP_LINES * 4);
1430
1431 DBG (DBG_proc, "sheetfed_calibration: start\n");
1432
1433 /* check calibration target has been loaded in ADF */
1434 status = test_document (dev->fd);
1435 if (status == SANE_STATUS_NO_DOCS)
1436 {
1437 DBG (DBG_error,
1438 "sheetfed_calibration: no calibration target present!\n");
1439 return SANE_STATUS_NO_DOCS;
1440 }
1441
1442 /* clean up calibration data */
1443 cleanup_calibration (dev);
1444
1445 /* a RGB scan to get reference data */
1446 /* initialize calibration slot for the resolution */
1447 i = 0;
1448 dpi = dev->model->max_xdpi;
1449 pixels = MAX_SENSOR_PIXELS;
1450 dev->calibration_data[i] =
1451 (P5_Calibration_Data *) malloc (sizeof (P5_Calibration_Data));
1452 if (dev->calibration_data[i] == NULL)
1453 {
1454 cleanup_calibration (dev);
1455 DBG (DBG_error,
1456 "sheetfed_calibration: failed to allocate memory for calibration\n");
1457 return SANE_STATUS_NO_MEM;
1458 }
1459 dev->calibration_data[i]->dpi = dpi;
1460
1461 /* start scan */
1462 status = start_scan (dev, MODE_COLOR, dpi, 0, pixels);
1463 if (status != SANE_STATUS_GOOD)
1464 {
1465 cleanup_calibration (dev);
1466 DBG (DBG_error,
1467 "sheetfed_calibration: failed to start scan at %d dpi\n", dpi);
1468 return SANE_STATUS_INVAL;
1469 }
1470
1471 white = 0;
1472 black = 0;
1473 read = 0;
1474 for (j = 0; j < pixels * 3; j++)
1475 {
1476 black_data[j] = 0;
1477 white_data[j] = 0;
1478 }
1479
1480 /* read lines and gather black and white ones until enough for sensor's
1481 * native resolution */
1482 do
1483 {
1484 status = test_document (dev->fd);
1485 if (status == SANE_STATUS_NO_DOCS && (white < 10 || black < 10))
1486 {
1487 cleanup_calibration (dev);
1488 DBG (DBG_error,
1489 "sheetfed_calibration: calibration sheet too short!\n");
1490 return SANE_STATUS_INVAL;
1491 }
1492 memset (buffer, 0x00, MAX_SENSOR_PIXELS * 3);
1493 line =
1494 read_line (dev, buffer, pixels * 3, 1, SANE_FALSE, SANE_FALSE,
1495 MODE_COLOR, SANE_FALSE);
1496 if (line == -1)
1497 {
1498 DBG (DBG_error, "sheetfed_calibration: failed to read data\n");
1499 return SANE_STATUS_INVAL;
1500 }
1501
1502 /* if a data line has been read, add it to reference data */
1503 if (line)
1504 {
1505 read++;
1506 fwrite (buffer, pixels * 3, 1, dbg);
1507 if (is_white_line (buffer, pixels, MODE_COLOR) && white < 256)
1508 {
1509 white++;
1510 /* first calibration lines are skipped */
1511 for (j = 0; j < pixels * 3 && read > CALIBRATION_SKIP_LINES;
1512 j++)
1513 {
1514 white_data[j] += buffer[j];
1515 }
1516 }
1517 if (is_black_line (buffer, pixels, MODE_COLOR) && black < 256)
1518 {
1519 black++;
1520 for (j = 0; j < pixels * 3; j++)
1521 {
1522 black_data[j] += buffer[j];
1523 }
1524 }
1525 }
1526 }
1527 while (test_document (dev->fd) != SANE_STATUS_NO_DOCS);
1528 DBG (DBG_trace, "sheetfed_calibration: white lines=%d, black lines=%d\n",
1529 white, black);
1530
1531 /* average pixels and store in per dpi calibration data */
1532 for (j = 0; j < pixels * 3; j++)
1533 {
1534 dev->calibration_data[i]->white_data[j] = white_data[j] / white;
1535 dev->calibration_data[i]->black_data[j] = black_data[j] / black;
1536 }
1537
1538 /* we average red, green and blue offset on the full sensor */
1539 red = 0;
1540 green = 0;
1541 blue = 0;
1542 for (j = 0; j < pixels * 3; j += 3)
1543 {
1544 red += dev->calibration_data[i]->black_data[j];
1545 green += dev->calibration_data[i]->black_data[j + 1];
1546 blue += dev->calibration_data[i]->black_data[j + 2];
1547 }
1548 for (j = 0; j < pixels * 3; j += 3)
1549 {
1550 dev->calibration_data[i]->black_data[j] = red / pixels;
1551 dev->calibration_data[i]->black_data[j + 1] = green / pixels;
1552 dev->calibration_data[i]->black_data[j + 2] = blue / pixels;
1553 }
1554
1555 /* trace calibration data for debug */
1556 if (DBG_LEVEL > DBG_data)
1557 {
1558 sprintf (title, "calibration-white-%d.pnm",
1559 dev->calibration_data[i]->dpi);
1560 write_rgb_data (title, dev->calibration_data[i]->white_data, pixels, 1);
1561 sprintf (title, "calibration-black-%d.pnm",
1562 dev->calibration_data[i]->dpi);
1563 write_rgb_data (title, dev->calibration_data[i]->black_data, pixels, 1);
1564 }
1565
1566 /* loop on all remaining resolution and compute calibration data from it */
1567 for (i = 1; i < MAX_RESOLUTIONS && dev->model->xdpi_values[i] > 0; i++)
1568 {
1569 dev->calibration_data[i] =
1570 (P5_Calibration_Data *) malloc (sizeof (P5_Calibration_Data));
1571 if (dev->calibration_data[i] == NULL)
1572 {
1573 cleanup_calibration (dev);
1574 DBG (DBG_error,
1575 "sheetfed_calibration: failed to allocate memory for calibration\n");
1576 return SANE_STATUS_INVAL;
1577 }
1578 dev->calibration_data[i]->dpi = dev->model->xdpi_values[i];
1579
1580 coeff = ((float) dev->model->xdpi_values[i]) / (float) dpi;
1581
1582 /* generate data by decimation */
1583 for (j = 0; j < pixels / coeff; j++)
1584 {
1585 k = j * coeff;
1586 dev->calibration_data[i]->white_data[j] =
1587 dev->calibration_data[0]->white_data[k];
1588 dev->calibration_data[i]->white_data[j + 1] =
1589 dev->calibration_data[0]->white_data[k + 1];
1590 dev->calibration_data[i]->white_data[j + 2] =
1591 dev->calibration_data[0]->white_data[k + 2];
1592 dev->calibration_data[i]->black_data[j] =
1593 dev->calibration_data[0]->black_data[k];
1594 dev->calibration_data[i]->black_data[j + 1] =
1595 dev->calibration_data[0]->black_data[k + 1];
1596 dev->calibration_data[i]->black_data[j + 2] =
1597 dev->calibration_data[0]->black_data[k + 2];
1598 }
1599 }
1600
1601 fclose (dbg);
1602 dev->calibrated = SANE_TRUE;
1603
1604 /* eject calibration target */
1605 eject (dev->fd);
1606
1607 DBG (DBG_proc, "sheetfed_calibration: end\n");
1608 return SANE_STATUS_GOOD;
1609 }
1610
1611 /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
1612