• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* sane - Scanner Access Now Easy.
2 
3    ScanMaker 3840 Backend
4    Copyright (C) 2005-7 Earle F. Philhower, III
5    earle@ziplabel.com - http://www.ziplabel.com
6 
7    This program is free software; you can redistribute it and/or
8    modify it under the terms of the GNU General Public License as
9    published by the Free Software Foundation; either version 2 of the
10    License, or (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <https://www.gnu.org/licenses/>.
19 
20    As a special exception, the authors of SANE give permission for
21    additional uses of the libraries contained in this release of SANE.
22 
23    The exception is that, if you link a SANE library with other files
24    to produce an executable, this does not by itself cause the
25    resulting executable to be covered by the GNU General Public
26    License.  Your use of that executable is in no way restricted on
27    account of linking the SANE library code into it.
28 
29    This exception does not, however, invalidate any other reasons why
30    the executable file might be covered by the GNU General Public
31    License.
32 
33    If you submit changes to SANE to the maintainers to be included in
34    a subsequent release, you agree by submitting the changes that
35    those changes may be distributed with this exception intact.
36 
37    If you write modifications of your own for SANE, it is your choice
38    whether to permit this exception to apply to your modifications.
39    If you do not wish that, delete this exception notice.
40 
41 */
42 
43 #include <stdio.h>
44 #include <stdarg.h>
45 #include <math.h>
46 #include "sm3840_lib.h"
47 
48 #ifndef BACKENDNAME
49 /* For standalone compilation */
50 static void
DBG(int ignored,const char * fmt,...)51 DBG (int ignored, const char *fmt, ...)
52 {
53   va_list a;
54   va_start (a, fmt);
55   vfprintf (stderr, fmt, a);
56   va_end (a);
57 }
58 #else
59 /* For SANE compilation, convert libusb to sanei_usb */
60 static int
my_usb_bulk_write(p_usb_dev_handle dev,int ep,unsigned char * bytes,int size,int timeout)61 my_usb_bulk_write (p_usb_dev_handle dev, int ep,
62 		   unsigned char *bytes, int size, int timeout)
63 {
64   SANE_Status status;
65   size_t my_size;
66 
67   (void) timeout;
68   (void) ep;
69   my_size = size;
70   status =
71     sanei_usb_write_bulk ((SANE_Int) dev, (SANE_Byte *) bytes, &my_size);
72   if (status != SANE_STATUS_GOOD)
73     my_size = -1;
74   return my_size;
75 }
76 
77 static int
my_usb_bulk_read(p_usb_dev_handle dev,int ep,unsigned char * bytes,int size,int timeout)78 my_usb_bulk_read (p_usb_dev_handle dev, int ep,
79 		  unsigned char *bytes, int size, int timeout)
80 {
81   SANE_Status status;
82   size_t my_size;
83 
84   (void) timeout;
85   (void) ep;
86   my_size = size;
87   status =
88     sanei_usb_read_bulk ((SANE_Int) dev, (SANE_Byte *) bytes, &my_size);
89   if (status != SANE_STATUS_GOOD)
90     my_size = -1;
91   return my_size;
92 }
93 
94 static int
my_usb_control_msg(p_usb_dev_handle dev,int requesttype,int request,int value,int index,unsigned char * bytes,int size,int timeout)95 my_usb_control_msg (p_usb_dev_handle dev, int requesttype,
96 		    int request, int value, int index,
97 		    unsigned char *bytes, int size, int timeout)
98 {
99   SANE_Status status;
100 
101   (void) timeout;
102   status = sanei_usb_control_msg ((SANE_Int) dev, (SANE_Int) requesttype,
103 				  (SANE_Int) request, (SANE_Int) value,
104 				  (SANE_Int) index, (SANE_Int) size,
105 				  (SANE_Byte *) bytes);
106   return status;
107 }
108 #endif
109 
110 
111 /* Sanitize and convert scan parameters from inches to pixels */
112 static void
prepare_params(SM3840_Params * params)113 prepare_params (SM3840_Params * params)
114 {
115   if (params->gray)
116     params->gray = 1;
117   if (params->lineart) {
118     params->gray = 1;
119     params->lineart = 1;
120   }
121   if (params->halftone) {
122     params->gray = 1;
123     params->halftone = 1;
124   }
125   if (params->dpi != 1200 && params->dpi != 600 && params->dpi != 300
126       && params->dpi != 150)
127     params->dpi = 150;
128   if (params->bpp != 8 && params->bpp != 16)
129     params->bpp = 8;
130 
131   /* Sanity check input sizes */
132   if (params->top < 0)
133     params->top = 0;
134   if (params->left < 0)
135     params->left = 0;
136   if (params->width < 0)
137     params->width = 0;
138   if (params->height < 0)
139     params->height = 0;
140   if ((params->top + params->height) > 11.7)
141     params->height = 11.7 - params->top;
142   if ((params->left + params->width) > 8.5)
143     params->width = 8.5 - params->left;
144 
145   params->topline = params->top * params->dpi;
146   params->scanlines = params->height * params->dpi;
147   params->leftpix = params->left * params->dpi;
148   params->leftpix &= ~1;	/* Always start on even pixel boundary for remap */
149   /* Scanpix always a multiple of 128 */
150   params->scanpix = params->width * params->dpi;
151   params->scanpix = (params->scanpix + 127) & ~127;
152 
153   /* Sanity check outputs... */
154   if (params->topline < 0)
155     params->topline = 0;
156   if (params->scanlines < 1)
157     params->scanlines = 1;
158   if (params->leftpix < 0)
159     params->leftpix = 0;
160   if (params->scanpix < 128)
161     params->scanpix = 128;
162 
163   /* Some handy calculations */
164   params->linelen =
165     params->scanpix * (params->bpp / 8) * (params->gray ? 1 : 3);
166 }
167 
168 #ifndef BACKENDNAME
169 usb_dev_handle *
find_device(unsigned int idVendor,unsigned int idProduct)170 find_device (unsigned int idVendor, unsigned int idProduct)
171 {
172   struct usb_bus *bus;
173   struct usb_device *dev;
174 
175   usb_init ();
176   usb_find_busses ();
177   usb_find_devices ();
178 
179   for (bus = usb_get_busses (); bus; bus = bus->next)
180     for (dev = bus->devices; dev; dev = dev->next)
181       if (dev->descriptor.idVendor == idVendor &&
182 	  dev->descriptor.idProduct == idProduct)
183 	return usb_open (dev);
184 
185   return NULL;
186 }
187 #endif
188 
189 static void
idle_ab(p_usb_dev_handle udev)190 idle_ab (p_usb_dev_handle udev)
191 {
192   int i;
193   unsigned char buff[8] = { 0x64, 0x65, 0x16, 0x17, 0x64, 0x65, 0x44, 0x45 };
194   for (i = 0; i < 8; i++)
195     {
196       usb_control_msg (udev, 0x40, 0x0c, 0x0090, 0x0000, buff + i,
197                        0x0001, wr_timeout);
198     }
199 }
200 
201 /* CW: 40 04 00b0 0000 <len> :  <reg1> <value1> <reg2> <value2> ... */
202 static void
write_regs(p_usb_dev_handle udev,int regs,int reg1,int val1,...)203 write_regs (p_usb_dev_handle udev, int regs, int reg1, int val1,
204 	    ... /* int reg, int val, ... */ )
205 {
206   unsigned char buff[512];
207   va_list marker;
208   int i;
209 
210   va_start (marker, val1);
211   buff[0] = reg1;
212   buff[1] = val1;
213   for (i = 1; i < regs; i++)
214     {
215       buff[i * 2] = va_arg (marker, int);
216       buff[i * 2 + 1] = va_arg (marker, int);
217     }
218   va_end (marker);
219 
220   usb_control_msg (udev, 0x40, 0x04, 0x00b0, 0x0000, buff,
221                    regs * 2, wr_timeout);
222 }
223 
224 static int
write_vctl(p_usb_dev_handle udev,int request,int value,int index,unsigned char byte)225 write_vctl (p_usb_dev_handle udev, int request, int value,
226 	    int index, unsigned char byte)
227 {
228   return usb_control_msg (udev, 0x40, request, value, index,
229 			  &byte, 1, wr_timeout);
230 }
231 
232 static int
read_vctl(p_usb_dev_handle udev,int request,int value,int index,unsigned char * byte)233 read_vctl (p_usb_dev_handle udev, int request, int value,
234 	   int index, unsigned char *byte)
235 {
236   return usb_control_msg (udev, 0xc0, request, value, index,
237 			  byte, 1, wr_timeout);
238 }
239 
240 #ifndef BACKENDNAME
241 /* Copy from a USB data pipe to a file with optional header */
242 static void
record_head(p_usb_dev_handle udev,char * fname,int bytes,char * header)243 record_head (p_usb_dev_handle udev, char *fname, int bytes, char *header)
244 {
245   FILE *fp;
246   unsigned char buff[65536];
247   int len;
248   int toread;
249 
250   fp = fopen (fname, "wb");
251   if (header)
252     fprintf (fp, "%s", header);
253   do
254     {
255       toread = (bytes > 65536) ? 65536 : bytes;
256       len = usb_bulk_read (udev, 1, buff, toread, rd_timeout);
257       if (len > 0)
258 	{
259 	  fwrite (buff, len, 1, fp);
260 	  bytes -= len;
261 	}
262       else
263 	{
264 	  DBG (2, "TIMEOUT\n");
265 	}
266     }
267   while (bytes);
268   fclose (fp);
269 }
270 
271 /* Copy from a USB data pipe to a file without header */
272 static void
record(p_usb_dev_handle udev,char * fname,int bytes)273 record (p_usb_dev_handle udev, char *fname, int bytes)
274 {
275   record_head (udev, fname, bytes, "");
276 }
277 #endif
278 
279 static int
max(int a,int b)280 max (int a, int b)
281 {
282   return (a > b) ? a : b;
283 }
284 
285 
286 #define DPI1200SHUFFLE 6
287 static void
record_line(int reset,p_usb_dev_handle udev,unsigned char * storeline,int dpi,int scanpix,int gray,int bpp16,int * save_i,unsigned char ** save_scan_line,unsigned char ** save_dpi1200_remap,unsigned char ** save_color_remap)288 record_line (int reset,
289 	     p_usb_dev_handle udev,
290 	     unsigned char *storeline,
291 	     int dpi, int scanpix, int gray, int bpp16,
292 	     int *save_i,
293 	     unsigned char **save_scan_line,
294 	     unsigned char **save_dpi1200_remap,
295 	     unsigned char **save_color_remap)
296 {
297   unsigned char *scan_line, *dpi1200_remap;
298   unsigned char *color_remap;
299   int i;
300   int red_delay, blue_delay, green_delay;
301   int j;
302   int linelen;
303   int pixsize;
304   unsigned char *ptrcur, *ptrprev;
305   unsigned char *savestoreline;
306   int lineptr, outline, bufflines;
307 
308   i = *save_i;
309   scan_line = *save_scan_line;
310   dpi1200_remap = *save_dpi1200_remap;
311   color_remap = *save_color_remap;
312 
313   pixsize = (gray ? 1 : 3) * (bpp16 ? 2 : 1);
314   linelen = scanpix * pixsize;
315 
316   if (gray)
317     {
318       red_delay = 0;
319       blue_delay = 0;
320       green_delay = 0;
321     }
322   else if (dpi == 150)
323     {
324       red_delay = 0;
325       blue_delay = 6;
326       green_delay = 3;
327     }
328   else if (dpi == 300)
329     {
330       red_delay = 0;
331       blue_delay = 12;
332       green_delay = 6;
333     }
334   else if (dpi == 600)
335     {
336       red_delay = 0;
337       blue_delay = 24;
338       green_delay = 12;
339     }
340   else				/*(dpi==1200) */
341     {
342       red_delay = 0;
343       blue_delay = 48;
344       green_delay = 24;
345     }
346 
347   bufflines = max (max (red_delay, blue_delay), green_delay) + 1;
348 
349   if (reset)
350     {
351       if (dpi1200_remap)
352 	free (dpi1200_remap);
353       if (scan_line)
354 	free (scan_line);
355       if (color_remap)
356 	free (color_remap);
357 
358       *save_color_remap = color_remap =
359 	(unsigned char *) malloc (bufflines * linelen);
360 
361       *save_scan_line = scan_line = (unsigned char *) calloc (linelen, 1);
362       if (dpi == 1200)
363 	*save_dpi1200_remap = dpi1200_remap =
364 	  (unsigned char *) calloc (linelen, DPI1200SHUFFLE);
365       else
366 	*save_dpi1200_remap = dpi1200_remap = NULL;
367 
368       *save_i = i = 0;		/* i is our linenumber */
369     }
370 
371   while (1)
372     {				/* We'll exit inside the loop... */
373       usb_bulk_read (udev, 1, scan_line, linelen, rd_timeout);
374       if (dpi == 1200)
375 	{
376 	  ptrcur = dpi1200_remap + (linelen * (i % DPI1200SHUFFLE));
377 	  ptrprev =
378 	    dpi1200_remap +
379 	    (linelen * ((i - (DPI1200SHUFFLE - 2)) % DPI1200SHUFFLE));
380 	}
381       else
382 	{
383 	  ptrcur = scan_line;
384 	  ptrprev = NULL;
385 	}
386       if (gray)
387 	{
388 	  memcpy (ptrcur, scan_line, linelen);
389 	}
390       else
391 	{
392 	  int pixsize = bpp16 ? 2 : 1;
393 	  int pix = linelen / (3 * pixsize);
394 	  unsigned char *outbuff = ptrcur;
395 
396 	  outline = i;
397 	  lineptr = i % bufflines;
398 
399 	  memcpy (color_remap + linelen * lineptr, scan_line, linelen);
400 
401 	  outline++;
402 	  if (outline > bufflines)
403 	    {
404 	      int redline = (outline + red_delay) % bufflines;
405 	      int greenline = (outline + green_delay) % bufflines;
406 	      int blueline = (outline + blue_delay) % bufflines;
407 	      unsigned char *rp, *gp, *bp;
408 
409 	      rp = color_remap + linelen * redline;
410 	      gp = color_remap + linelen * greenline + 1 * pixsize;
411 	      bp = color_remap + linelen * blueline + 2 * pixsize;
412 
413 	      for (j = 0; j < pix; j++)
414 		{
415 		  if (outbuff)
416 		    {
417 		      *(outbuff++) = *rp;
418 		      if (pixsize == 2)
419 			*(outbuff++) = *(rp + 1);
420 		      *(outbuff++) = *gp;
421 		      if (pixsize == 2)
422 			*(outbuff++) = *(gp + 1);
423 		      *(outbuff++) = *bp;
424 		      if (pixsize == 2)
425 			*(outbuff++) = *(bp + 1);
426 		    }
427 		  rp += 3 * pixsize;
428 		  gp += 3 * pixsize;
429 		  bp += 3 * pixsize;
430 		}
431 	    }
432 	  lineptr = (lineptr + 1) % bufflines;
433 	}
434 
435       if (dpi != 1200)
436 	{
437 	  if (i > blue_delay)
438 	    {
439 	      savestoreline = storeline;
440 	      for (j = 0; j < scanpix; j++)
441 		{
442 		  memcpy (storeline, ptrcur + linelen - (j + 1) * pixsize,
443 			  pixsize);
444 		  storeline += pixsize;
445 		}
446 	      if (dpi == 150)
447 		{
448 		  /* 150 DPI skips every 4th returned line */
449 		  if (i % 4)
450 		    {
451 		      i++;
452 		      *save_i = i;
453 		      if (bpp16)
454 			fix_endian_short ((unsigned short *) storeline,
455 					  scanpix);
456 		      return;
457 		    }
458 		  storeline = savestoreline;
459 		}
460 	      else
461 		{
462 		  i++;
463 		  *save_i = i;
464 		  if (bpp16)
465 		    fix_endian_short ((unsigned short *) storeline, scanpix);
466 		  return;
467 		}
468 	    }
469 	}
470       else			/* dpi==1200 */
471 	{
472 	  if (i > (DPI1200SHUFFLE + blue_delay))
473 	    {
474 	      for (j = 0; j < scanpix; j++)
475 		{
476 		  if (1 == (j & 1))
477 		    memcpy (storeline, ptrcur + linelen - (j + 1) * pixsize,
478 			    pixsize);
479 		  else
480 		    memcpy (storeline, ptrprev + linelen - (j + 1) * pixsize,
481 			    pixsize);
482 		  storeline += pixsize;
483 		}		/* end for */
484 	      i++;
485 	      *save_i = i;
486 	      if (bpp16)
487 		fix_endian_short ((unsigned short *) storeline, scanpix);
488 	      return;
489 	    }			/* end if >dpi1200shuffle */
490 	}			/* end if dpi1200 */
491       i++;
492     }				/* end for */
493 }
494 
495 
496 #ifndef BACKENDNAME
497 /* Record an image to a file with remapping/reordering/etc. */
498 void
record_image(p_usb_dev_handle udev,char * fname,int dpi,int scanpix,int scanlines,int gray,char * head,int bpp16)499 record_image (p_usb_dev_handle udev, char *fname, int dpi,
500 	      int scanpix, int scanlines, int gray, char *head, int bpp16)
501 {
502   FILE *fp;
503   int i;
504   int save_i;
505   unsigned char *save_scan_line;
506   unsigned char *save_dpi1200_remap;
507   unsigned char *save_color_remap;
508   unsigned char *storeline;
509 
510   save_i = 0;
511   save_scan_line = save_dpi1200_remap = save_color_remap = NULL;
512   storeline =
513     (unsigned char *) malloc (scanpix * (gray ? 1 : 3) * (bpp16 ? 2 : 1));
514 
515   fp = fopen (fname, "wb");
516   if (head)
517     fprintf (fp, "%s", head);
518 
519   for (i = 0; i < scanlines; i++)
520     {
521       record_line ((i == 0) ? 1 : 0, udev, storeline, dpi, scanpix, gray,
522 		   bpp16, &save_i, &save_scan_line, &save_dpi1200_remap,
523 		   &save_color_remap);
524       fwrite (storeline, scanpix * (gray ? 1 : 3) * (bpp16 ? 2 : 1), 1, fp);
525     }
526   fclose (fp);
527   if (save_scan_line)
528     free (save_scan_line);
529   if (save_dpi1200_remap)
530     free (save_dpi1200_remap);
531   if (save_color_remap)
532     free (save_color_remap);
533   free (storeline);
534 }
535 #endif
536 
537 static void
record_mem(p_usb_dev_handle udev,unsigned char ** dest,int bytes)538 record_mem (p_usb_dev_handle udev, unsigned char **dest, int bytes)
539 {
540   unsigned char *mem;
541   unsigned char buff[65536];
542   int len;
543 
544   mem = (unsigned char *) malloc (bytes);
545   *dest = mem;
546   do
547     {
548       len =
549 	usb_bulk_read (udev, 1, buff, bytes > 65536 ? 65536 : bytes,
550 		       rd_timeout);
551       if (len > 0)
552 	{
553 	  memcpy (mem, buff, len);
554 	  bytes -= len;
555 	  mem += len;
556 	}
557     }
558   while (bytes);
559 }
560 
561 
562 static void
reset_scanner(p_usb_dev_handle udev)563 reset_scanner (p_usb_dev_handle udev)
564 {
565   unsigned char rd_byte;
566 
567   DBG (2, "+reset_scanner\n");
568   write_regs (udev, 5, 0x83, 0x00, 0xa3, 0xff, 0xa4, 0xff, 0xa1, 0xff,
569 	      0xa2, 0xff);
570   write_vctl (udev, 0x0c, 0x0001, 0x0000, 0x00);
571   write_regs (udev, 2, 0xbe, 0x00, 0x84, 0x00);
572   write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00);
573   write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00);
574   write_regs (udev, 16, 0xbe, 0x18, 0x80, 0x00, 0x84, 0x00, 0x89, 0x00,
575 	      0x88, 0x00, 0x86, 0x00, 0x90, 0x00, 0xc1, 0x00,
576 	      0xc2, 0x00, 0xc3, 0x00, 0xc4, 0x00, 0xc5, 0x00,
577 	      0xc6, 0x00, 0xc7, 0x00, 0xc8, 0x00, 0xc0, 0x00);
578   write_regs (udev, 16, 0x84, 0x94, 0x80, 0xd1, 0x80, 0xc1, 0x82, 0x7f,
579 	      0xcf, 0x04, 0xc1, 0x02, 0xc2, 0x00, 0xc3, 0x06,
580 	      0xc4, 0xff, 0xc5, 0x40, 0xc6, 0x8c, 0xc7, 0xdc,
581 	      0xc8, 0x20, 0xc0, 0x72, 0x89, 0xff, 0x86, 0xff);
582   write_regs (udev, 7, 0xa8, 0x80, 0x83, 0xa2, 0x85, 0xc8, 0x83, 0x82,
583 	      0x85, 0xaf, 0x83, 0x00, 0x93, 0x00);
584   write_regs (udev, 3, 0xa8, 0x0a, 0x8c, 0x08, 0x94, 0x00);
585   write_regs (udev, 4, 0x83, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0x97, 0x0a);
586   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
587   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
588   write_regs (udev, 1, 0x97, 0x0b);
589   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
590   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
591   write_regs (udev, 1, 0x97, 0x0f);
592   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
593   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
594   write_regs (udev, 1, 0x97, 0x05);
595   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
596   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
597   DBG (2, "-reset_scanner\n");
598 }
599 
600 static void
poll1(p_usb_dev_handle udev)601 poll1 (p_usb_dev_handle udev)
602 {
603   unsigned char rd_byte;
604   DBG (2, "+poll1\n");
605   do
606     {
607       write_regs (udev, 1, 0x97, 0x00);
608       write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
609       read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
610     }
611   while (0 == (rd_byte & 0x40));
612   DBG (2, "-poll1\n");
613 }
614 
615 static void
poll2(p_usb_dev_handle udev)616 poll2 (p_usb_dev_handle udev)
617 {
618   unsigned char rd_byte;
619   DBG (2, "+poll2\n");
620   do
621     {
622       write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
623       read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
624     }
625   while (0 == (rd_byte & 0x02));
626   DBG (2, "-poll2\n");
627 }
628 
629 #ifndef BACKENDNAME
630 static void
check_buttons(p_usb_dev_handle udev,int * scan,int * print,int * mail)631 check_buttons (p_usb_dev_handle udev, int *scan, int *print, int *mail)
632 {
633   unsigned char rd_byte;
634 
635   write_regs (udev, 4, 0x83, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0x97, 0x0a);
636   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
637   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
638   if (scan)
639     {
640       if (0 == (rd_byte & 1))
641 	*scan = 1;
642       else
643 	*scan = 0;
644     }
645   if (print)
646     {
647       if (0 == (rd_byte & 2))
648 	*print = 1;
649       else
650 	*print = 0;
651     }
652   if (mail)
653     {
654       if (0 == (rd_byte & 4))
655 	*mail = 1;
656       else
657 	*mail = 0;
658     }
659   write_regs (udev, 1, 0x97, 0x0b);
660   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
661   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
662   idle_ab (udev);
663   write_regs (udev, 1, 0x97, 0x0f);
664   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
665   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
666   idle_ab (udev);
667   write_regs (udev, 1, 0x97, 0x05);
668   write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00);
669   read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte);
670   idle_ab (udev);
671 }
672 #endif
673 
674 static int
lut(int val,double gain,int offset)675 lut (int val, double gain, int offset)
676 {
677   /* int offset = 1800; */
678   /* double exponent = 3.5; */
679   return (offset + 8192.0 * (pow ((8192.0 - val) / 8192.0, gain)));
680 }
681 
682 
683 static void
calc_lightmap(unsigned short * buff,unsigned short * storage,int index,int dpi,double gain,int offset)684 calc_lightmap (unsigned short *buff,
685 	       unsigned short *storage, int index, int dpi,
686 	       double gain, int offset)
687 {
688   int val, line;
689   int px = 5632;
690   int i;
691 
692   line = px * 3;
693 
694   for (i = 0; i < px; i++)
695     {
696       if ((i >= 2) && (i <= (px - 2)))
697 	{
698 	  val = 0;
699 	  val += 1 * buff[i * 3 + index - 3 * 2];
700 	  val += 3 * buff[i * 3 + index - 3 * 1];
701 	  val += 5 * buff[i * 3 + index + 3 * 0];
702 	  val += 3 * buff[i * 3 + index + 3 * 1];
703 	  val += 1 * buff[i * 3 + index + 3 * 2];
704 	  val += 2 * buff[i * 3 + index - 3 * 1 + line];
705 	  val += 3 * buff[i * 3 + index + 3 * 0 + line];
706 	  val += 2 * buff[i * 3 + index + 3 * 1 + line];
707 	  val += 1 * buff[i * 3 + index + 3 * 0 + 2 * line];
708 	  val /= 21;
709 	}
710       else
711 	{
712 	  val = 1 * buff[i * 3 + index];
713 	}
714 
715       val = val >> 3;
716       if (val > 8191)
717 	val = 8191;
718       val = lut (val, gain, offset);
719 
720       if (val > 8191)
721 	val = 8191;
722       if (val < 0)
723 	val = 0;
724       storage[i * (dpi == 1200 ? 2 : 1)] = val;
725       if (dpi == 1200)
726 	storage[i * 2 + 1] = val;
727     }
728 
729   fix_endian_short (storage, (dpi == 1200) ? i * 2 : i);
730 }
731 
732 
733 
734 
735 /*#define VALMAP  0x1fff */
736 /*#define SCANMAP 0x2000*/
737 #define RAWPIXELS600 7320
738 #define RAWPIXELS1200 14640
739 
740 static void
select_pixels(unsigned short * map,int dpi,int start,int end)741 select_pixels (unsigned short *map, int dpi, int start, int end)
742 {
743   int i;
744   int skip, offset;
745   unsigned short VALMAP = 0x1fff;
746   unsigned short SCANMAP = 0x2000;
747 
748   fix_endian_short (&VALMAP, 1);
749   fix_endian_short (&SCANMAP, 1);
750 
751   /* Clear the pixel-on flags for all bits */
752   for (i = 0; i < ((dpi == 1200) ? RAWPIXELS1200 : RAWPIXELS600); i++)
753     map[i] &= VALMAP;
754 
755   /* 300 and 150 have subsampling */
756   if (dpi == 300)
757     skip = -2;
758   else if (dpi == 150)
759     skip = -4;
760   else
761     skip = -1;
762 
763   /* 1200 has 2x pixels so start at 2x the offset */
764   if (dpi == 1200)
765     offset = 234 + (8.5 * 1200);
766   else
767     offset = 117 + (8.5 * 600);
768 
769   if (0 == (offset & 1))
770     offset++;
771 
772   DBG (2, "offset=%d start=%d skip=%d\n", offset, start, skip);
773 
774   for (i = 0; i < end; i++)
775     {
776       int x;
777       x = offset + (start * skip) + (i * skip);
778       if (x < 0 || x > ((dpi == 1200) ? RAWPIXELS1200 : RAWPIXELS600))
779 	DBG (2, "ERR %d\n", x);
780       else
781 	map[x] |= SCANMAP;
782     }
783 }
784 
785 
786 static void
set_lightmap_white(unsigned short * map,int dpi,int color)787 set_lightmap_white (unsigned short *map, int dpi, int color)
788 {
789   int i;
790   unsigned short VALMAP = 0x1fff;
791   unsigned short SCANMAP = 0x2000;
792 
793   fix_endian_short (&VALMAP, 1);
794   fix_endian_short (&SCANMAP, 1);
795 
796   if (dpi != 1200)
797     {
798       memset (map, 0, RAWPIXELS600 * 2);
799       if (color != 0)
800 	return;			/* Only 1st has enables... */
801       for (i = 0; i < 22; i++)
802 	map[7 + i] = SCANMAP;	/* Get some black... */
803       for (i = 0; i < 1024; i++)
804 	map[2048 + i] = SCANMAP;	/* And some white... */
805     }
806   else
807     {
808       memset (map, 0, RAWPIXELS1200 * 2);
809       if (color != 0)
810 	return;
811       for (i = 16; i < 61; i++)
812 	map[i] = SCANMAP;
813       for (i = 4076; i < 6145; i++)
814 	map[i] = SCANMAP;
815       /* 3rd is all clear */
816     }
817 }
818 
819 
820 static void
set_lamp_timer(p_usb_dev_handle udev,int timeout_in_mins)821 set_lamp_timer (p_usb_dev_handle udev, int timeout_in_mins)
822 {
823   write_regs (udev, 7, 0xa8, 0x80, 0x83, 0xa2, 0x85, 0xc8, 0x83, 0x82,
824 	      0x85, 0xaf, 0x83, 0x00, 0x93, 0x00);
825   write_regs (udev, 3, 0xa8, timeout_in_mins * 2, 0x8c, 0x08, 0x94, 0x00);
826   idle_ab (udev);
827   write_regs (udev, 4, 0x83, 0x20, 0x8d, 0x26, 0x83, 0x00, 0x8d, 0xff);
828 }
829 
830 
831 static void
calculate_lut8(double * poly,int skip,unsigned char * dest)832 calculate_lut8 (double *poly, int skip, unsigned char *dest)
833 {
834   int i;
835   double sum, x;
836   if (!poly || !dest)
837     return;
838   for (i = 0; i < 8192; i += skip)
839     {
840       sum = poly[0];
841       x = (double) i;
842       sum += poly[1] * x;
843       x = x * i;
844       sum += poly[2] * x;
845       x = x * i;
846       sum += poly[3] * x;
847       x = x * i;
848       sum += poly[4] * x;
849       x = x * i;
850       sum += poly[5] * x;
851       x = x * i;
852       sum += poly[6] * x;
853       x = x * i;
854       sum += poly[7] * x;
855       x = x * i;
856       sum += poly[8] * x;
857       x = x * i;
858       sum += poly[9] * x;
859       x = x * i;
860       if (sum < 0)
861 	sum = 0;
862       if (sum > 255)
863 	sum = 255;
864       *dest = (unsigned char) sum;
865       dest++;
866     }
867 }
868 
869 static void
download_lut8(p_usb_dev_handle udev,int dpi,int incolor)870 download_lut8 (p_usb_dev_handle udev, int dpi, int incolor)
871 {
872   double color[10] = { 0.0, 1.84615261590892E-01, -2.19613868292657E-04,
873     1.79549523214101E-07, -8.69378513113239E-11,
874     2.56694911984996E-14, -4.67288886157239E-18,
875     5.11622894146250E-22, -3.08729724411991E-26,
876     7.88581670873938E-31
877   };
878   double gray[10] = { 0.0, 1.73089945056694E-01, -1.39794924306080E-04,
879     9.70266873814926E-08, -4.57503008236968E-11,
880     1.37092321631794E-14, -2.54395068387198E-18,
881     2.82432084125966E-22, -1.71787408822688E-26,
882     4.40306800664567E-31
883   };
884   unsigned char *lut;
885 
886   DBG (2, "+download_lut8\n");
887   switch (dpi)
888     {
889     case 150:
890     case 300:
891     case 600:
892       lut = (unsigned char *) malloc (4096);
893       if (!lut)
894 	return;
895 
896       if (!incolor)
897 	{
898 	  calculate_lut8 (gray, 2, lut);
899 	  write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x20, 0xb2, 0x07, 0xb3, 0xff,
900 		      0xb4, 0x2f, 0xb5, 0x07);
901 	  write_vctl (udev, 0x0c, 0x0002, 0x1000, 0x00);
902 	  usb_bulk_write (udev, 2, lut, 4096, wr_timeout);
903 	}
904       else
905 	{
906 	  calculate_lut8 (color, 2, lut);
907 	  write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x10, 0xb2, 0x07, 0xb3, 0xff,
908 		      0xb4, 0x1f, 0xb5, 0x07);
909 	  write_vctl (udev, 0x0c, 0x0002, 0x1000, 0x00);
910 	  usb_bulk_write (udev, 2, lut, 4096, wr_timeout);
911 	  write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x20, 0xb2, 0x07, 0xb3, 0xff,
912 		      0xb4, 0x2f, 0xb5, 0x07);
913 	  write_vctl (udev, 0x0c, 0x0002, 0x1000, 0x00);
914 	  usb_bulk_write (udev, 2, lut, 4096, wr_timeout);
915 	  write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x30, 0xb2, 0x07, 0xb3, 0xff,
916 		      0xb4, 0x3f, 0xb5, 0x07);
917 	  write_vctl (udev, 0x0c, 0x0002, 0x1000, 0x00);
918 	  usb_bulk_write (udev, 2, lut, 4096, wr_timeout);
919 	}
920       break;
921 
922     case 1200:
923     default:
924       lut = (unsigned char *) malloc (8192);
925       if (!lut)
926 	return;
927 
928       if (!incolor)
929 	{
930 	  calculate_lut8 (gray, 1, lut);
931 	  write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x40, 0xb2, 0x06, 0xb3, 0xff,
932 		      0xb4, 0x5f, 0xb5, 0x06);
933 	  write_vctl (udev, 0x0c, 0x0002, 0x2000, 0x00);
934 	  usb_bulk_write (udev, 2, lut, 8192, wr_timeout);
935 	}
936       else
937 	{
938 	  calculate_lut8 (color, 1, lut);
939 	  write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x20, 0xb2, 0x06, 0xb3, 0xff,
940 		      0xb4, 0x3f, 0xb5, 0x06);
941 	  write_vctl (udev, 0x0c, 0x0002, 0x2000, 0x00);
942 	  usb_bulk_write (udev, 2, lut, 8192, wr_timeout);
943 	  write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x40, 0xb2, 0x06, 0xb3, 0xff,
944 		      0xb4, 0x5f, 0xb5, 0x06);
945 	  write_vctl (udev, 0x0c, 0x0002, 0x2000, 0x00);
946 	  usb_bulk_write (udev, 2, lut, 8192, wr_timeout);
947 	  write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x60, 0xb2, 0x06, 0xb3, 0xff,
948 		      0xb4, 0x7f, 0xb5, 0x06);
949 	  write_vctl (udev, 0x0c, 0x0002, 0x2000, 0x00);
950 	  usb_bulk_write (udev, 2, lut, 8192, wr_timeout);
951 	}
952       break;
953     }
954 
955   free (lut);
956   DBG (2, "-download_lut8\n");
957 }
958 
959 
960 static void
set_gain_black(p_usb_dev_handle udev,int r_gain,int g_gain,int b_gain,int r_black,int g_black,int b_black)961 set_gain_black (p_usb_dev_handle udev,
962 		int r_gain, int g_gain, int b_gain,
963 		int r_black, int g_black, int b_black)
964 {
965   write_regs (udev, 1, 0x80, 0x00);
966   write_regs (udev, 1, 0x80, 0x01);
967   write_regs (udev, 1, 0x04, 0x80);
968   write_regs (udev, 1, 0x04, 0x00);
969   write_regs (udev, 1, 0x00, 0x00);
970   write_regs (udev, 1, 0x01, 0x03);
971   write_regs (udev, 1, 0x02, 0x04);
972   write_regs (udev, 1, 0x03, 0x11);
973   write_regs (udev, 1, 0x05, 0x00);
974   write_regs (udev, 1, 0x28, r_gain);
975   write_regs (udev, 1, 0x29, g_gain);
976   write_regs (udev, 1, 0x2a, b_gain);
977   write_regs (udev, 1, 0x20, r_black);
978   write_regs (udev, 1, 0x21, g_black);
979   write_regs (udev, 1, 0x22, b_black);
980   write_regs (udev, 1, 0x24, 0x00);
981   write_regs (udev, 1, 0x25, 0x00);
982   write_regs (udev, 1, 0x26, 0x00);
983 }
984 
985 /* Handle short endianness issues */
986 static void
fix_endian_short(unsigned short * data,int count)987 fix_endian_short (unsigned short *data, int count)
988 {
989   unsigned short testvalue = 255;
990   unsigned char *firstbyte = (unsigned char *) &testvalue;
991   int i;
992 
993   if (*firstbyte == 255)
994     return;			/* INTC endianness */
995 
996   DBG (2, "swapping endianness...\n");
997   for (i = 0; i < count; i++)
998     data[i] = ((data[i] >> 8) & 0x00ff) | ((data[i] << 8) & 0xff00);
999 }
1000