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