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