• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* sane - Scanner Access Now Easy.
2 
3    Copyright (C) 1999 Paul Mackerras
4    Copyright (C) 2000 Adrian Perez Jorge
5    Copyright (C) 2001 Frank Zago
6    Copyright (C) 2001 Marcio Teixeira
7    Parts copyright (C) 2006 Patrick Lessard
8 
9    This file is part of the SANE package.
10 
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License as
13    published by the Free Software Foundation; either version 2 of the
14    License, or (at your option) any later version.
15 
16    This program is distributed in the hope that it will be useful, but
17    WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    General Public License for more details.
20 
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <https://www.gnu.org/licenses/>.
23 
24    As a special exception, the authors of SANE give permission for
25    additional uses of the libraries contained in this release of SANE.
26 
27    The exception is that, if you link a SANE library with other files
28    to produce an executable, this does not by itself cause the
29    resulting executable to be covered by the GNU General Public
30    License.  Your use of that executable is in no way restricted on
31    account of linking the SANE library code into it.
32 
33    This exception does not, however, invalidate any other reasons why
34    the executable file might be covered by the GNU General Public
35    License.
36 
37    If you submit changes to SANE to the maintainers to be included in
38    a subsequent release, you agree by submitting the changes that
39    those changes may be distributed with this exception intact.
40 
41    If you write modifications of your own for SANE, it is your choice
42    whether to permit this exception to apply to your modifications.
43    If you do not wish that, delete this exception notice.
44 
45    Defines a driver and API for accessing the UMAX Astra 1220U
46    USB scanner. Based on the original command line tool by Paul
47    Mackerras.
48 
49    The UMAX Astra 1220U scanner uses the PowerVision PV8630
50    Parallel Port to USB bridge. This chip is also used
51    by the HP4200C flatbed scanner. Adrian Perez Jorge wrote
52    a nice interface file for that chip and Frank Zago adapted
53    it to use the sanei_usb interface. Thanks, guys, for making
54    my life easier! :)
55 
56  */
57 
58 
59 #include <string.h>
60 #include <errno.h>
61 #include <fcntl.h>
62 #include <sys/types.h>
63 #include <sys/stat.h>
64 #include <sys/ioctl.h>
65 #include <math.h>
66 
67 /*
68  * The backend performs test scans in order to calibrate
69  * the CCD and to find the zero location. If you would like
70  * to look at those scans, define DEBUG_CALIBRATION to have
71  * the backend save "find_zero.pgm" and "calibration.pgm" to
72  * disk.
73  */
74 /* #define DEBUG_CALIBRATION */
75 
76 /*
77  * Define DEBUG_BOUNDS to insert paranoid array bounds
78  * overrun detection into the code.
79  */
80 /* #define DEBUG_BOUNDS */
81 
82 /* These values are empirically determined and are given
83  * in 1/600 inch units. If UMAX_MAX_HEIGHT is too large,
84  * the scanner may grind its gears. I assume there is a
85  * physical limit to UMAX_MAX_WIDTH as well (based on the
86  * sensor size) but I do not know what it is. The current
87  * value can be increased beyond what it is now, but you
88  * gain nothing in usable scan area (you only scan more
89  * of the underside of the scanner's plastic lid).
90  */
91 
92 
93 #define UMAX_MAX_WIDTH    5400
94 #define UMAX_MAX_HEIGHT   7040
95 
96 /* Buffer size. Specifies the size of the buffer that is
97  * used to copy data from the scanner. The old command
98  * line driver had this set at 0x80000 which is likely
99  * the largest possible chunk of data that can be.
100  * at once. This is probably most efficient, but using
101  * a lower value for the SANE driver makes the driver
102  * more responsive to interaction.
103  */
104 #define BUFFER_SIZE 0x80000
105 
106 /* Constants that can be used with set_lamp_state to
107  * control the state of the scanner's lamp
108  */
109 typedef enum
110 {
111   UMAX_LAMP_OFF = 0,
112   UMAX_LAMP_ON = 1
113 }
114 UMAX_Lamp_State;
115 
116 /* Constants that can be used with move to control
117  * the rate of scanner head movement
118  */
119 typedef enum
120 {
121   UMAX_NOT_FINE = 0,
122   UMAX_FINE = 1
123 }
124 UMAX_Speed;
125 
126 /* If anyone knows some descriptive names for these,
127  * please update
128  */
129 typedef enum
130 {
131   CMD_0 = 0x00,
132   CMD_1 = 0x01,
133   CMD_2 = 0x02,
134   CMD_4 = 0x04,
135   CMD_8 = 0x08,
136   CMD_40 = 0x40,
137   CMD_WRITE = 0x80,
138   CMD_READ = 0xc0
139 }
140 UMAX_Cmd;
141 
142 /* Product IDs for Astra scanners
143  */
144 typedef enum
145 {
146   ASTRA_1220U = 0x0010,
147   ASTRA_2000U = 0x0030,
148   ASTRA_2100U = 0x0130
149 }
150 UMAX_Model;
151 
152 /* The bytes UMAX_SYNC1 and UMAX_SYNC2 serve as a
153  * synchronization signal. Unintentional sync bytes
154  * in the data stream are escaped with UMAX_ESCAPE
155  * character
156  */
157 
158 #define UMAX_SYNC1  0x55
159 #define UMAX_SYNC2  0xaa
160 #define UMAX_ESCAPE 0x1b
161 
162 /* Status bits. These bits are active low.
163  * In umax_pp, UMAX_REVERSE_BIT is called
164  * MOTOR_BIT.
165  */
166 
167 #define UMAX_FORWARD_BIT       0x40
168 #define UMAX_ERROR_BIT         0x20
169 #define UMAX_MOTOR_OFF_BIT     0x08
170 
171 #define UMAX_OK                0x48        /* Used to be 0xC8 */
172 #define UMAX_OK_WITH_MOTOR     0x40        /* Used to be 0xD0 */
173 
174 #define UMAX_STATUS_MASK       0x68
175 
176 /* This byte is used as a placeholder for bytes that are parameterized
177  * in the opcode strings */
178 
179 #define XXXX 0x00
180 
181 /* This macro is used to check the return code of
182  * functions
183  */
184 #define CHK(A) {if( (res = A) != SANE_STATUS_GOOD ) { \
185                  DBG( 1, "Failure on line of %s: %d\n", __FILE__, \
186                       __LINE__ ); return A; }}
187 
188 /* Macros that are used for array overrun detection
189  * (when DEBUG_BOUNDS is defined)
190  */
191 #ifdef DEBUG_BOUNDS
192 #define PAD 10
193 #define PAD_ARRAY( A, len ) {int i; \
194                  for( i = 0; i < PAD; i++ ) {A[len+i]=0x55;}}
195 
196 #define CHK_ARRAY( A, len ) {int i;for( i = 0; i < PAD; i++ ) {\
197    if(A[len+i]!=0x55) { \
198      DBG( 1, "Array overrun detected on line %d\n", __LINE__ ); \
199    }}}
200 #else
201 #define PAD 0
202 #define PAD_ARRAY( A, len )
203 #define CHK_ARRAY( A, len )
204 #endif
205 
206 
207 /* This data structure contains data related
208  * to the scanning process.
209  */
210 typedef struct
211 {
212   /* Constant data */
213 
214   int color;
215   int w;
216   int h;
217   int xo;
218   int yo;
219   int xdpi;                      /* Physical x dpi */
220   int ydpi;                      /* Physical y dpi */
221   int xsamp;
222   int ysamp;
223 
224   int xskip;
225   int yskip;
226 
227   int fd;                        /* Device file handle */
228   UMAX_Model model;
229 
230   /* Raw scan data buffer */
231 
232   unsigned char *p;
233   int bh;                        /* Size of buffer in lines    */
234   int hexp;                      /* Scan lines yet to be read  */
235 
236   /* Decoding logic */
237 
238   int x, y, maxh;
239   int done;                      /* Boolean, all lines decoded */
240 
241   /* Calibration data */
242 
243   unsigned char caldata[16070 + PAD];
244 
245   /* Scan head position */
246 
247   int scanner_ypos;
248   int scanner_yorg;
249 }
250 UMAX_Handle;
251 
252 typedef unsigned char UMAX_Status_Byte;
253 
254 
255 #if 0
256 static void
257 unused_operations ()
258 {
259   /* These operations are unused anywhere in the driver */
260 
261   unsigned char opb8[35] = {
262     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04,
263     0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0x18, 0x10, 0x03,
264     0x06, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a,
265     0xd0, 0x68, 0xdf, 0x13, 0x1a
266   };
267 
268   unsigned char opb9[35] = {
269     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04,
270     0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0x41, 0x20, 0x24,
271     0x06, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a,
272     0xd0, 0x68, 0xdf, 0x13, 0x1a
273   };
274 
275   unsigned char opb10[35] = {
276     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04,
277     0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0x41, 0x60, 0x4f,
278     0x06, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a,
279     0xd0, 0x68, 0xdf, 0x93, 0x1a
280   };
281 
282   unsigned char opc5[16] = {
283     0x05, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2f, 0x00,
284     0x00, 0x30, 0x0c, 0xc3, 0xa4, 0x00
285   };
286 
287   unsigned char opc6[16] = {
288     0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2f, 0x00,
289     0x88, 0x48, 0x0c, 0x83, 0xa4, 0x00
290   };
291 
292   unsigned char opc7[16] = {
293     0x05, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2f, 0x00,
294     0xec, 0x4e, 0x0c, 0xc3, 0xa4, 0x00
295   };
296 
297   unsigned char opd2[8] = {
298     0x06, 0xf4, 0xff, 0x81, 0x3d, 0x00, 0x00, 0x30
299   };
300 }
301 #endif
302 
303 #if 0
304 static SANE_Status
305 calib (UMAX_Handle * scan)
306 {
307   unsigned char buf[65536];
308   opc5[11] = 0x30;
309   opd2[7]  = 0x30;
310   CHK (get_pixels (scan, opc5, opb8, opd2, ope, 24, 0, buff));
311 
312   opc5[11] = 0x40;
313   opd2[7]  = 0x40;
314   CHK (get_pixels (scan, opc5, opb8, opd2, ope, 24, 0, buff));
315 
316   opd2[6] = 8;
317   opd2[7] = 0x30;
318   CHK (get_pixels (scan, opc6, opb9, opd2, ope, 0x200, 1, buff));
319 
320   opc7[10] = 0xec;
321   opd2[6]  = 0xc;
322   opd2[7]  = 0x40;
323   CHK (get_pixels (scan, opc7, opb10, opd2, ope, 5300, 1, buff));
324 
325   opc7[10] = 0xed;
326   opd2[6]  = 0xd;
327   CHK (get_pixels (scan, opc7, opb10, opd2, ope, 5300, 0, buff));
328   return SANE_STATUS_GOOD;
329 }
330 #endif
331 
332 
333 /* This seems to configure the pv8630 chip somehow. I wish
334  * all the magic numbers were defined as self-descriptive
335  * constants somewhere. I made some guesses based on what
336  * I found in "pv8630.c", but alas there wasn't enough in
337  * there. If you know what this does, please let me know!
338  */
339 static SANE_Status
xxxops(UMAX_Handle * scan)340 xxxops (UMAX_Handle * scan)
341 {
342   SANE_Status res;
343 
344   DBG (9, "doing xxxops\n");
345 
346   CHK (sanei_pv8630_write_byte (scan->fd, PV8630_RMODE, 0x02));
347 
348   CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x0E));
349   CHK (sanei_pv8630_write_byte (scan->fd, PV8630_RDATA, 0x40));
350   CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x06));
351   CHK (sanei_pv8630_xpect_byte (scan->fd, PV8630_RSTATUS, 0x38, 0xFF));
352 
353   CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x07));
354   CHK (sanei_pv8630_xpect_byte (scan->fd, PV8630_RSTATUS, 0x38, 0xFF));
355 
356   CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x04));
357   CHK (sanei_pv8630_xpect_byte (scan->fd, PV8630_RSTATUS, 0xF8, 0xFF));
358 
359   CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x05));
360   CHK (sanei_pv8630_xpect_byte (scan->fd, PV8630_UNKNOWN, 0x05, 0xFF));
361 
362   CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x04));
363 
364   CHK (sanei_pv8630_write_byte (scan->fd, PV8630_RMODE, 0x1E));
365 
366   return res;
367 }
368 
369 /*
370 Apparently sends the two synchronization characters followed
371 by the command length, followed by the command number
372 */
373 static SANE_Status
usync(UMAX_Handle * scan,UMAX_Cmd cmd,int len)374 usync (UMAX_Handle * scan, UMAX_Cmd cmd, int len)
375 {
376   UMAX_Status_Byte s0, s4;
377   SANE_Status res;
378   unsigned char buf[4];
379   size_t nb;
380 
381   DBG (80, "usync: len = %d, cmd = %d\n", len, cmd);
382 
383   buf[0] = UMAX_SYNC1;
384   buf[1] = UMAX_SYNC2;
385 
386   nb = 2;
387   CHK (sanei_pv8630_flush_buffer (scan->fd));
388   CHK (sanei_pv8630_prep_bulkwrite (scan->fd, nb));
389   CHK (sanei_pv8630_bulkwrite (scan->fd, buf, &nb));
390 
391   CHK (sanei_pv8630_wait_byte
392        (scan->fd, PV8630_RSTATUS, UMAX_OK, UMAX_STATUS_MASK, 20));
393 
394   buf[0] = len >> 16;
395   buf[1] = len >> 8;
396   buf[2] = len;
397   buf[3] = cmd;
398 
399   nb = 4;
400   CHK (sanei_pv8630_flush_buffer (scan->fd));
401   CHK (sanei_pv8630_prep_bulkwrite (scan->fd, nb));
402   CHK (sanei_pv8630_bulkwrite (scan->fd, buf, &nb));
403 
404   CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RDATA, &s0));
405   CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RSTATUS, &s4));
406 
407   DBG (90, "usync: s0 = %#x s4 = %#x\n", s0, s4);
408 
409   return SANE_STATUS_GOOD;
410 }
411 
412 /*
413 This function escapes any synchronization sequence that may be
414 in data, storing the result in buf. In the worst case where
415 every character gets escaped buf must be at least twice as
416 large as dlen.
417 */
418 static int
bescape(const unsigned char * data,int dlen,unsigned char * buf,int blen)419 bescape (const unsigned char *data, int dlen, unsigned char *buf, int blen)
420 {
421   const unsigned char *p;
422   unsigned char *q;
423   int i, c;
424   i = blen;   /* Eliminate compiler warning about unused param */
425 
426   p = data;
427   q = buf;
428   for (i = 0; i < dlen; ++i)
429     {
430       c = *p++;
431       if (c == UMAX_ESCAPE
432           || (c == UMAX_SYNC2 && i > 0 && p[-2] == UMAX_SYNC1))
433         *q++ = UMAX_ESCAPE;
434       *q++ = c;
435     }
436   return q - buf;
437 }
438 
439 
440 
441 /* Write */
442 
443 static SANE_Status
cwrite(UMAX_Handle * scan,UMAX_Cmd cmd,size_t len,const unsigned char * data,UMAX_Status_Byte * s)444 cwrite (UMAX_Handle * scan, UMAX_Cmd cmd, size_t len, const unsigned char *data,
445         UMAX_Status_Byte * s)
446 {
447   SANE_Status res;
448   UMAX_Status_Byte s0, s4;
449 
450   static unsigned char *escaped = NULL;
451   static size_t escaped_size = 0;
452 
453   DBG (80, "cwrite: cmd = %d, len = %lu\n", cmd, (u_long) len);
454 
455   CHK (usync (scan, cmd | CMD_WRITE, len));
456 
457   if (len <= 0)
458     return SANE_STATUS_GOOD;
459 
460   if (escaped_size < len * 2)
461     {
462       escaped_size = len * 2;
463       if (escaped)
464         free (escaped);
465       escaped = malloc (escaped_size);
466       if (escaped == NULL)
467         return SANE_STATUS_NO_MEM;
468     }
469 
470   len = bescape (data, len, escaped, len * 2);
471 
472   CHK (sanei_pv8630_wait_byte
473        (scan->fd, PV8630_RSTATUS, UMAX_OK, UMAX_STATUS_MASK, 20));
474 
475   CHK (sanei_pv8630_flush_buffer (scan->fd));
476   CHK (sanei_pv8630_prep_bulkwrite (scan->fd, len));
477   CHK (sanei_pv8630_bulkwrite (scan->fd, escaped, &len));
478 
479   CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RSTATUS, &s4));
480   CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RDATA, &s0));
481 
482   DBG (90, "cwrite: s0 = %#x s4 = %#x\n", s0, s4);
483 
484   if (s)
485     *s = s0;
486 
487   return SANE_STATUS_GOOD;
488 }
489 
490 /* Read */
491 
492 static SANE_Status
cread(UMAX_Handle * scan,UMAX_Cmd cmd,size_t len,unsigned char * data,UMAX_Status_Byte * s)493 cread (UMAX_Handle * scan, UMAX_Cmd cmd, size_t len, unsigned char *data,
494        UMAX_Status_Byte * s)
495 {
496   SANE_Status res;
497   UMAX_Status_Byte s0, s4;
498 
499   DBG (80, "cread: cmd = %d, len = %lu\n", cmd, (u_long) len);
500 
501   CHK (usync (scan, cmd | CMD_READ, len));
502 
503   if (len > 0)
504     {
505       CHK (sanei_pv8630_wait_byte
506            (scan->fd, PV8630_RSTATUS, UMAX_OK_WITH_MOTOR, UMAX_STATUS_MASK,
507             2000));
508 
509       while (len > 0)
510         {
511           size_t req, n;
512 
513           req = n = (len > 0xf000) ? 0xf000 : len;
514           CHK (sanei_pv8630_prep_bulkread (scan->fd, n));
515           CHK (sanei_pv8630_bulkread (scan->fd, data, &n));
516           if (n < req)
517             {
518               DBG (1, "qread: Expecting to read %lu, only got %lu\n", (u_long) req, (u_long) n);
519               return SANE_STATUS_IO_ERROR;
520             }
521           data += n;
522           len -= n;
523         }
524     }
525 
526   CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RSTATUS, &s4));
527   CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RDATA, &s0));
528 
529   DBG (90, "cwrite: s0 = %#x s4 = %#x\n", s0, s4);
530 
531   if (s)
532     *s = s0;
533 
534   return SANE_STATUS_GOOD;
535 }
536 
537 
538 
539 /* Seems to be like cwrite, with a verification option */
540 
541 static SANE_Status
cwritev(UMAX_Handle * scan,UMAX_Cmd cmd,size_t len,const unsigned char * data,UMAX_Status_Byte * s)542 cwritev (UMAX_Handle * scan, UMAX_Cmd cmd, size_t len, const unsigned char *data,
543          UMAX_Status_Byte * s)
544 {
545   SANE_Status res;
546   unsigned char buf[16384];
547 
548   /* Write out the opcode */
549 
550   CHK (cwrite (scan, cmd, len, data, s));
551   if (len <= 0)
552     return SANE_STATUS_GOOD;
553 
554   /* Read the opcode back */
555 
556   CHK (cread (scan, cmd, len, buf, NULL));
557   if (bcmp (buf, data, len))
558     {
559       DBG (1, "cwritev: verification failed\n");
560       return SANE_STATUS_IO_ERROR;
561     }
562   return SANE_STATUS_GOOD;
563 }
564 
565 
566 /* Send command */
567 
568 static SANE_Status
csend(UMAX_Handle * scan,UMAX_Cmd cmd)569 csend (UMAX_Handle * scan, UMAX_Cmd cmd)
570 {
571   DBG (80, "csend: cmd = %d\n", cmd);
572 
573   return usync (scan, cmd, 0);
574 }
575 
576 /* Lamp control */
577 
578 static SANE_Status
cwritev_opc1_lamp_ctrl(UMAX_Handle * scan,UMAX_Lamp_State state)579 cwritev_opc1_lamp_ctrl (UMAX_Handle * scan, UMAX_Lamp_State state)
580 {
581   unsigned char opc1[16] = {
582     0x01, 0x00, 0x01, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x13, 0x05,
583     0x00, 0x00, 0x00, 0x80, 0xf0, 0x00
584   };
585 
586   DBG (9, "cwritev_opc1: set lamp state = %s\n",
587        (state == UMAX_LAMP_OFF) ? "off" : "on");
588   opc1[14] = (state == UMAX_LAMP_OFF) ? 0x90 : 0xf0;
589   return cwritev (scan, CMD_2, 16, opc1, NULL);
590 }
591 
592 
593 /* Restore Head 1220U */
594 
595 static SANE_Status
cwritev_opb3_restore(UMAX_Handle * scan)596 cwritev_opb3_restore (UMAX_Handle * scan)
597 {
598   unsigned char opb3[35] = {
599     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03,
600     0xc1, 0x80, 0x00, 0x00, 0x04, 0x00, 0x16, 0x80, 0x15, 0x78,
601     0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a,
602     0xd0, 0x68, 0xdf, 0x1b, 0x1a,
603   };
604 
605   SANE_Status res;
606 
607   DBG (9, "cwritev_opb3_restore:\n");
608   CHK (cwritev (scan, CMD_8, 35, opb3, NULL));
609   CHK (csend (scan, CMD_40));
610   return SANE_STATUS_GOOD;
611 }
612 
613 
614 /* Restore Head 2100U */
615 
616 static SANE_Status
cwritev_opb3_restore_2100U(UMAX_Handle * scan)617 cwritev_opb3_restore_2100U (UMAX_Handle * scan)
618 {
619   unsigned char opb3[36] = {
620     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03,
621     0xc1, 0x80, 0x00, 0x00, 0x04, 0x00, 0x16, 0x80, 0x15, 0x78,
622     0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x2a,
623     0xe9, 0x68, 0xdf, 0x0b, 0x1a, 0x00
624   };
625 
626   SANE_Status res;
627 
628   DBG (9, "cwritev_opb3_restore:\n");
629   CHK (cwritev (scan, CMD_8, 36, opb3, NULL));
630   CHK (csend (scan, CMD_40));
631   return SANE_STATUS_GOOD;
632 }
633 
634 
635 /* Initialize and turn lamp on 1220U */
636 
637 /*
638 This function seems to perform various things. First, it loads a default
639 gamma information (which is used for the calibration scan), returns the
640 head to the park position, and turns the lamp on. This function used to
641 be split up into two parts, umaxinit and umaxinit2.
642 */
643 
644 static SANE_Status
umaxinit(UMAX_Handle * scan)645 umaxinit (UMAX_Handle * scan)
646 {
647   unsigned char opb[34] = {
648     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03,
649     0xc1, 0x80, 0x60, 0x20, 0x00, 0x00, 0x16, 0x41, 0xe0, 0xac,
650     0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x00, 0x00, 0x00,
651     0x00, 0x00, 0x00, 0xf0
652   };
653   unsigned char opb1[35] = {
654     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03,
655     0xc1, 0x80, 0x00, 0x20, 0x02, 0x00, 0x16, 0x41, 0xe0, 0xac,
656     0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x00, 0x00, 0x00,
657     0x00, 0x00, 0x00, 0x10, 0x1a
658   };
659   unsigned char opb2[35] = {
660     0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03,
661     0xc1, 0x80, 0x00, 0x20, 0x02, 0x00, 0x16, 0x41, 0xe0, 0xac,
662     0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x00, 0x00, 0x00,
663     0x00, 0x00, 0x00, 0x10, 0x1a
664   };
665   unsigned char opb4[35] = {
666     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03,
667     0xc1, 0x80, 0x60, 0x20, 0x00, 0x00, 0x16, 0x41, 0xe0, 0xac,
668     0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a,
669     0xd0, 0x68, 0xdf, 0xf3, 0x1b
670   };
671   unsigned char opbx[35];
672   unsigned char opc[16] = {
673     0x02, 0x80, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2f, 0x07,
674     0x00, 0x00, 0x00, 0x80, 0xf0, 0x00
675   };
676   unsigned char opcx[16];
677   unsigned char opd[8] = {
678     0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa
679   };
680 
681   SANE_Status res;
682   UMAX_Status_Byte s;
683   unsigned char ramp[800];
684   int i;
685   unsigned char *p;
686 
687   DBG (3, "umaxinit called\n");
688 
689   CHK (csend (scan, CMD_0));
690   CHK (xxxops (scan));
691 
692   CHK (cwritev (scan, CMD_8, 34, opb, &s));
693   CHK (cread (scan, CMD_8, 35, opbx, &s));
694 
695   CHK (cwritev (scan, CMD_8, 35, opb1, &s));
696 
697   CHK (cread (scan, CMD_2, 0, NULL, &s));
698 
699   DBG (4, "umaxinit: checkpoint 2:\n");
700 
701   /* The following code appears to send three 256 entry, 8-bit gamma tables
702    * to the scanner
703    */
704   p = ramp;
705   *p++ = 0;
706   *p++ = 0;
707   *p++ = 0;
708   for (i = 0; i < 256; ++i)
709     *p++ = i;
710   for (i = 0; i < 256; ++i)
711     *p++ = i;
712   for (i = 0; i < 256; ++i)
713     *p++ = i;
714   *p++ = 0xaa;
715   *p++ = 0xaa;
716 
717   res = cwritev (scan, CMD_4, p - ramp, ramp, &s);
718   if (res != SANE_STATUS_GOOD)
719     {
720       DBG (4, "umaxinit: Writing ramp 1 failed (is this a 2000U?)\n");
721     }
722   CHK (cwritev (scan, CMD_8, 35, opb1, &s));
723 
724   CHK (cread (scan, CMD_2, 0, NULL, &s));
725 
726   DBG (4, "umaxinit: checkpoint 3:\n");
727 
728   /* The following code appears to send a 256 entry, 16-bit gamma table
729    * to the scanner
730    */
731   p = ramp;
732   for (i = 0; i < 256; ++i)
733     {
734       *p++ = i;
735       *p++ = 0;
736     }
737 
738   res = cwrite (scan, CMD_4, p - ramp, ramp, &s);
739   if (res != SANE_STATUS_GOOD)
740     {
741       DBG (4, "umaxinit: Writing ramp 2 failed (is this a 2000U?)\n");
742     }
743   CHK (cwritev (scan, CMD_8, 35, opb2, &s));
744 
745   CHK (cread (scan, CMD_2, 0, NULL, &s));
746 
747   DBG (4, "umaxinit: checkpoint 4:\n");
748 
749   /* The following code appears to send a 256 entry, 16-bit gamma table
750    * to the scanner.
751    */
752   p = ramp;
753   for (i = 0; i < 256; ++i)
754     {
755       *p++ = i;
756       *p++ = 4;
757     }
758 
759   res = cwritev (scan, CMD_4, p - ramp, ramp, &s);
760   if (res != SANE_STATUS_GOOD)
761     {
762       DBG (4, "umaxinit: Writing ramp 3 failed (is this a 2000U?)\n");
763     }
764   CHK (cwritev (scan, CMD_8, 35, opb1, &s));
765 
766   CHK (cwritev (scan, CMD_2, 16, opc, NULL));
767   CHK (cwritev (scan, CMD_1, 8, opd, NULL));
768   CHK (csend (scan, CMD_0));
769   CHK (cread (scan, CMD_2, 0, NULL, &s));
770 
771   DBG (4, "umaxinit: checkpoint 5: s = %#x\n", s);
772 
773   if ((s & 0x40) == 0)
774     {
775       DBG (4, "umaxinit: turning on lamp and restoring\n");
776       CHK (cwritev_opc1_lamp_ctrl (scan, UMAX_LAMP_ON));
777       CHK (cwritev_opb3_restore (scan));
778 
779       for (i = 0; i < 60; ++i)
780         {
781           CHK (cread (scan, CMD_2, 0, NULL, &s));
782           DBG (4, "umaxinit: s = %#x\n", s);
783           if ((s & 0x40) != 0)
784             break;
785           DBG (4, "umaxinit: sleeping\n");
786           usleep (500000);
787         }
788     }
789 
790   DBG (4, "umaxinit: checkpoint 6\n");
791 
792   CHK (csend (scan, CMD_0));
793 
794   /* The following stuff used to be in umaxinit2() */
795 
796   DBG (4, "umaxinit: checkpoint 7\n");
797 
798   CHK (xxxops (scan));
799   CHK (csend (scan, CMD_0));
800   CHK (xxxops (scan));
801 
802   CHK (cwritev (scan, CMD_8, 34, opb4, &s));
803   CHK (cread (scan, CMD_8, 35, opbx, &s));
804   CHK (cread (scan, CMD_2, 16, opcx, &s));
805 
806   CHK (cwritev (scan, CMD_2, 16, opc, NULL));
807   CHK (cwritev (scan, CMD_1, 8, opd, NULL));
808   CHK (csend (scan, CMD_0));
809   CHK (cread (scan, CMD_2, 0, NULL, &s));
810 
811   DBG (4, "umaxinit: checkpoint 8: s = %d\n", s);
812 
813   return SANE_STATUS_GOOD;
814 }
815 
816 /* Initialize and turn lamp on 2100U */
817 
818 static SANE_Status
umaxinit_2100U(UMAX_Handle * scan)819 umaxinit_2100U (UMAX_Handle * scan)
820 {
821 
822   unsigned char opx[36];
823   unsigned char opy[16];
824 
825 
826   SANE_Status res;
827   UMAX_Status_Byte s;
828 
829   DBG (3, "umaxinit called\n");
830 
831   CHK (xxxops (scan));
832   CHK (csend (scan, CMD_0));
833 
834   /* Turn lamp on */
835 
836   cwritev_opc1_lamp_ctrl (scan, UMAX_LAMP_ON);
837 
838   CHK (cread (scan, CMD_8, 36, opx, &s));
839   CHK (cread (scan, CMD_2, 16, opy, &s));
840   CHK (csend (scan, CMD_0));
841   CHK (cread (scan, CMD_2, 0, NULL, &s));
842   CHK (csend (scan, CMD_0));
843 
844   return SANE_STATUS_GOOD;
845 }
846 
847 
848 /* Move head 1220U */
849 
850 static SANE_Status
move(UMAX_Handle * scan,int distance,UMAX_Speed fine)851 move (UMAX_Handle * scan, int distance, UMAX_Speed fine)
852 {
853   unsigned char opc4[16] = {
854     0x01, XXXX, XXXX, XXXX, 0x00, 0x00, 0x60, 0x2f, XXXX, XXXX,
855     0x00, 0x00, 0x00, 0x80, XXXX, 0x00
856   };
857   unsigned char opb5[35] = {
858     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04,
859     0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xf6, 0x79, 0xbf,
860     0x06, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a,
861     0xd0, 0x68, 0xdf, 0x13, 0x1a
862   };
863   unsigned char opb7[35] = {
864     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
865     0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xf6, 0x79, 0xbf,
866     0x01, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a,
867     0xd0, 0x68, 0xdf, 0x13, 0x1a
868   };
869 
870   unsigned char ope[8] = {
871     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
872   };
873 
874   unsigned char ope2[3] = {
875     0x00, 0xff, 0x8f
876   };
877   unsigned char buf[512 + PAD];
878 
879   SANE_Status res;
880   UMAX_Status_Byte s;
881 
882   SANE_Bool rev = distance < 0;
883   int skip = (rev ? -distance : distance) - 1;
884 
885   DBG (9, "move: distance = %d, scanner_ypos = %d\n", distance,
886        scan->scanner_ypos);
887 
888   PAD_ARRAY (buf, 512);
889 
890   if (distance == 0)
891     return SANE_STATUS_GOOD;
892 
893   opc4[1] = skip << 6;
894   opc4[2] = skip >> 2;
895   opc4[3] = (rev ? 0x20 : 0x70) + ((skip >> 10) & 0xf);
896   opc4[9] = rev ? 0x01 : 0x05;
897 
898   if (fine == UMAX_FINE)
899     {
900       opc4[8]  = 0x2f;
901       opc4[14] = 0xa4;
902     }
903   else
904     {
905       opc4[8]  = 0x17;
906       opc4[14] = 0xac;
907     }
908 
909   scan->scanner_ypos +=
910     (fine == UMAX_FINE ? distance : 2 * distance + (rev ? -1 : 1));
911   scan->scanner_ypos = (scan->scanner_ypos + (rev ? 0 : 3)) & ~3;
912 
913   CHK (cwrite (scan, CMD_2, 16, opc4, &s));
914   CHK (cwrite (scan, CMD_8, 35, rev ? opb7 : opb5, &s));
915 
916   CHK (cread (scan, CMD_2, 0, NULL, &s));
917   DBG (10, "move: checkpoint 1: s = %d\n", s);
918 
919   CHK (csend (scan, CMD_0));
920   if (rev)
921     CHK (cwrite (scan, CMD_4, 3, ope2, &s))
922   else
923     CHK (cwrite (scan, CMD_4, 8, ope, &s));
924 
925 
926   CHK (csend (scan, CMD_40));
927 
928   CHK (cread (scan, CMD_2, 0, NULL, &s));
929 
930   DBG (10, "move: checkpoint 2: s = %d\n", s);
931 
932   CHK (cread (scan, CMD_2, 0, NULL, &s));
933   DBG (10, "move: checkpoint 3: s = %d\n", s);
934 
935   CHK (cread (scan, CMD_4, 512, buf, &s));
936 
937   CHK_ARRAY (buf, 512);
938 
939   return res;
940 }
941 
942 
943 
944 /* Move head 2100U */
945 
946 static SANE_Status
move_2100U(UMAX_Handle * scan,int distance,UMAX_Speed fine)947 move_2100U (UMAX_Handle * scan, int distance, UMAX_Speed fine)
948 {
949 
950 
951   unsigned char opc4[16] = {
952     0x01, XXXX, XXXX, XXXX, 0x00, 0x00, 0x60, 0x2f, XXXX, XXXX,
953     0x00, 0x00, 0x00, 0x80, XXXX, 0x00
954   };
955   unsigned char opb5[36] = {
956     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04,
957     0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xf6, 0x79, 0xbf,
958     0x06, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x2a,
959     0xe9, 0x68, 0xdf, 0x03, 0x1a, 0x00
960   };
961   unsigned char opb7[36] = {
962     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
963     0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xf6, 0x79, 0xbf,
964     0x01, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x2a,
965     0xe9, 0x68, 0xdf, 0x03, 0x1a, 0x00
966   };
967   unsigned char ope[8] = {
968     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
969   };
970   unsigned char ope2[3] = {
971     0x00, 0xff, 0xff
972   };
973   unsigned char buf[512];
974 
975 
976   SANE_Status res;
977   UMAX_Status_Byte s;
978 
979   SANE_Bool rev = distance < 0;
980   int skip = (rev ? -distance : distance) - 1;
981 
982   DBG (9, "move: distance = %d, scanner_ypos = %d\n", distance,
983        scan->scanner_ypos);
984 
985   PAD_ARRAY (buf, 512);
986 
987   if (distance == 0)
988     return SANE_STATUS_GOOD;
989 
990   opc4[1] = skip << 6;
991   opc4[2] = skip >> 2;
992   opc4[3] = (rev ? 0x20 : 0x70) + ((skip >> 10) & 0x0f);
993   opc4[9] = rev ? 0x01 : 0x05;
994 
995   if (fine == UMAX_FINE)
996     {
997       opc4[8]  = 0x2b;
998       opc4[14] = 0xa4;
999     }
1000   else
1001     {
1002       opc4[8]  = 0x15;
1003       opc4[14] = 0xac;
1004     }
1005 
1006   scan->scanner_ypos +=
1007     (fine == UMAX_FINE ? distance : 2 * distance + (rev ? -1 : 1));
1008   scan->scanner_ypos = (scan->scanner_ypos + (rev ? 0 : 3)) & ~3;
1009 
1010   CHK (cwrite (scan, CMD_2, 16, opc4, &s));
1011   CHK (cwrite (scan, CMD_8, 36, rev ? opb7 : opb5, &s));
1012 
1013   CHK (cread (scan, CMD_2, 0, NULL, &s));
1014   DBG (10, "move: checkpoint 1: s = %d\n", s);
1015 
1016   CHK (csend (scan, CMD_0));
1017 
1018   if (rev)
1019     CHK (cwrite (scan, CMD_4, 3, ope2, &s))
1020   else
1021     CHK (cwrite (scan, CMD_4, 8, ope, &s));
1022 
1023   CHK (csend (scan, CMD_40));
1024 
1025   CHK (cread (scan, CMD_2, 0, NULL, &s));
1026 
1027   DBG (10, "move: checkpoint 2: s = %d\n", s);
1028 
1029   CHK (cread (scan, CMD_2, 0, NULL, &s));
1030   DBG (10, "move: checkpoint 3: s = %d\n", s);
1031 
1032   CHK (cread (scan, CMD_4, 512, buf, &s));
1033 
1034   CHK_ARRAY (buf, 512);
1035 
1036   return res;
1037 }
1038 
1039 
1040 /* Get pixel image 1220U */
1041 
1042 static SANE_Status
get_pixels(UMAX_Handle * scan,unsigned char * op2,unsigned char * op8,unsigned char * op1,unsigned char * op4,int len,int zpos,unsigned char * buf)1043 get_pixels (UMAX_Handle * scan, unsigned char *op2, unsigned char *op8,
1044             unsigned char *op1, unsigned char *op4, int len, int zpos,
1045             unsigned char *buf)
1046 {
1047   SANE_Status res;
1048   UMAX_Status_Byte s;
1049 
1050   DBG (9, "get_pixels: len = %d, zpos = %d\n", len, zpos);
1051 
1052   if (zpos == 0)
1053     CHK (csend (scan, CMD_0));
1054 
1055   CHK (cwrite (scan, CMD_2, 16, op2, &s));
1056   CHK (cwrite (scan, CMD_8, 35, op8, &s));
1057   CHK (cwrite (scan, CMD_1, 8, op1, &s));
1058   CHK (cread (scan, CMD_2, 0, NULL, &s));
1059 
1060   if (zpos == 1)
1061     CHK (csend (scan, CMD_0));
1062 
1063   CHK (cwrite (scan, CMD_4, 8, op4, &s));
1064   CHK (csend (scan, CMD_40));
1065   CHK (cread (scan, CMD_2, 0, NULL, &s));
1066 
1067   CHK (cread (scan, CMD_2, 0, NULL, &s));
1068 
1069   CHK (cread (scan, CMD_4, len, buf, &s));
1070   return SANE_STATUS_GOOD;
1071 }
1072 
1073 
1074 /* Get pixel image 2100U */
1075 
1076 static SANE_Status
get_pixels_2100U(UMAX_Handle * scan,unsigned char * op2,unsigned char * op8,unsigned char * op1,unsigned char * op4,int len,int zpos,unsigned char * buf)1077 get_pixels_2100U (UMAX_Handle * scan, unsigned char *op2, unsigned char *op8,
1078             unsigned char *op1, unsigned char *op4, int len, int zpos,
1079             unsigned char *buf)
1080 {
1081   SANE_Status res;
1082   UMAX_Status_Byte s;
1083 
1084   DBG (9, "get_pixels: len = %d, zpos = %d\n", len, zpos);
1085 
1086   CHK (cwrite (scan, CMD_2, 16, op2, &s));
1087   CHK (cwrite (scan, CMD_8, 36, op8, &s));
1088 
1089   if (zpos == 1)
1090     CHK (cwritev (scan, CMD_1, 8, op1, &s))
1091   else
1092     CHK (cwrite (scan, CMD_1, 8, op1, &s));
1093 
1094   CHK (cread (scan, CMD_2, 0, NULL, &s));
1095 
1096   if (zpos == 1)
1097     CHK (csend (scan, CMD_0));
1098 
1099   CHK (cwrite (scan, CMD_4, 8, op4, &s));
1100   CHK (csend (scan, CMD_40));
1101   CHK (cread (scan, CMD_2, 0, NULL, &s));
1102 
1103   CHK (cread (scan, CMD_2, 0, NULL, &s));
1104 
1105   CHK (cread (scan, CMD_4, len, buf, &s));
1106   return SANE_STATUS_GOOD;
1107 }
1108 
1109 
1110 /* This function locates the black stripe under scanner lid */
1111 
1112 static int
locate_black_stripe(unsigned char * img,int w,int h)1113 locate_black_stripe (unsigned char *img, int w, int h)
1114 {
1115   int epos, ecnt, x, y;
1116   unsigned char *p;
1117 
1118   epos = 0;
1119   ecnt = 0;
1120   p = img;
1121   for (x = 0; x < w; ++x, ++p)
1122     {
1123       int d, dmax = 0, dpos = 0;
1124       unsigned char *q = img + x;
1125       for (y = 1; y < h; ++y, q += w)
1126         {
1127           d = q[0] - q[w];
1128           if (d > dmax)
1129             {
1130               dmax = d;
1131               dpos = y;
1132             }
1133         }
1134       if (dmax > 0)
1135         {
1136           epos += dpos;
1137           ++ecnt;
1138         }
1139     }
1140   if (ecnt == 0)
1141     epos = 70;
1142   else
1143     epos = (epos + ecnt / 2) / ecnt;
1144   return epos;
1145 }
1146 
1147 
1148 /* To find the lowest head position 1220U */
1149 
1150 static SANE_Status
find_zero(UMAX_Handle * scan)1151 find_zero (UMAX_Handle * scan)
1152 {
1153   unsigned char opc3[16] = {
1154     0xb4, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2f, 0x05,
1155     0x00, 0x00, 0x00, 0x80, 0xa4, 0x00
1156   };
1157   unsigned char ope1[8] = {
1158     0x00, 0x00, 0x00, 0xaa, 0xcc, 0xee, 0x80, 0xff
1159   };
1160   unsigned char opb6[35] = {
1161     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04,
1162     0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xfb, 0xc4, 0xe5,
1163     0x06, 0x00, 0x00, 0x60, 0x4d, 0xa0, 0x00, 0x8b, 0x49, 0x4a,
1164     0xd0, 0x68, 0xdf, 0x13, 0x1a
1165   };
1166   unsigned char opd1[8] = {
1167     0x06, 0xf4, 0xff, 0x81, 0x3d, 0x00, 0x08, 0x00
1168   };
1169 
1170   SANE_Status res;
1171   int s;
1172   unsigned char *img;
1173 
1174   DBG (9, "find_zero:\n");
1175 
1176   img = malloc (54000);
1177   if (img == 0)
1178     {
1179       DBG (1, "out of memory (need 54000)\n");
1180       return SANE_STATUS_NO_MEM;
1181     }
1182 
1183   CHK (csend (scan, CMD_0));
1184   CHK (get_pixels (scan, opc3, opb6, opd1, ope1, 54000, 1, img));
1185 
1186 #ifdef DEBUG_CALIBRATION
1187   {
1188     int w = 300, h = 180;
1189     FILE *f2 = fopen ("find_zero.pgm", "wb");
1190     fprintf (f2, "P5\n%d %d\n255\n", w, h);
1191     fwrite (img, 1, w * h, f2);
1192     fclose (f2);
1193   }
1194 #endif
1195 
1196   s = locate_black_stripe (img, 300, 180);
1197   scan->scanner_yorg = scan->scanner_ypos + s + 64;
1198   scan->scanner_ypos += 180 + 3;
1199   scan->scanner_ypos &= ~3;
1200 
1201   free (img);
1202   return SANE_STATUS_GOOD;
1203 }
1204 
1205 
1206 /* To find the lowest head position 2100U */
1207 
1208 static SANE_Status
find_zero_2100U(UMAX_Handle * scan)1209 find_zero_2100U (UMAX_Handle * scan)
1210 {
1211   unsigned char opc3[16] = {
1212     0xb4, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2b, 0x05,
1213     0x00, 0x00, 0x00, 0x80, 0xa4, 0x00
1214   };
1215   unsigned char ope1[8] = {
1216     0x00, 0x00, 0x00, 0xaa, 0xcc, 0xee, 0x80, 0xff
1217   };
1218   unsigned char opb6[36] = {
1219     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04,
1220     0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xfb, 0xc4, 0xe5,
1221     0x06, 0x00, 0x00, 0x60, 0x4d, 0xa0, 0x00, 0x8b, 0x49, 0x2a,
1222     0xe9, 0x68, 0xdf, 0x03, 0x1a, 0x00
1223   };
1224   unsigned char opd1[8] = {
1225     0x06, 0xf4, 0xff, 0x81, 0x1b, 0x00, 0x08, 0x00
1226   };
1227 
1228   SANE_Status res;
1229   int s;
1230   unsigned char *img;
1231 
1232   DBG (9, "find_zero:\n");
1233 
1234   img = malloc (54000);
1235   if (img == 0)
1236     {
1237       DBG (1, "out of memory (need 54000)\n");
1238       return SANE_STATUS_NO_MEM;
1239     }
1240 
1241   CHK (csend (scan, CMD_0));
1242   CHK (get_pixels_2100U (scan, opc3, opb6, opd1, ope1, 54000, 1, img));
1243 
1244 #ifdef DEBUG_CALIBRATION
1245   {
1246     int w = 300, h = 180;
1247     FILE *f2 = fopen ("find_zero.pgm", "wb");
1248     fprintf (f2, "P5\n%d %d\n255\n", w, h);
1249     fwrite (img, 1, w * h, f2);
1250     fclose (f2);
1251   }
1252 #endif
1253 
1254   s = locate_black_stripe (img, 300, 180);
1255   scan->scanner_yorg = scan->scanner_ypos + s + 64;
1256   scan->scanner_ypos += 180 + 3;
1257   scan->scanner_ypos &= ~3;
1258 
1259   free (img);
1260   return SANE_STATUS_GOOD;
1261 }
1262 
1263 
1264 /* Calibration 1220U */
1265 
1266 /*
1267 Format of caldata:
1268 
1269    5100 bytes of CCD calibration values
1270    5100 bytes of CCD calibration values
1271    5100 bytes of CCD calibration values
1272    256 bytes of gamma data for blue
1273    256 bytes of gamma data for green
1274    256 bytes of gamma data for red
1275    2 bytes of extra information
1276 
1277 */
1278 static SANE_Status
get_caldata(UMAX_Handle * scan,int color)1279 get_caldata (UMAX_Handle * scan, int color)
1280 {
1281   unsigned char opc9[16] = {
1282     XXXX, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x17, 0x05,
1283     0xec, 0x4e, 0x0c, XXXX, 0xac
1284   };
1285   unsigned char opb11[35] = {
1286     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04,
1287     0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xad, 0xa0, 0x49,
1288     0x06, 0x00, 0x00, XXXX, XXXX, 0xa0, 0x00, 0x8b, 0x49, 0x4a,
1289     0xd0, 0x68, 0xdf, 0x93, 0x1b
1290   };
1291 
1292   unsigned char ope[8] = {
1293     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1294   };
1295 
1296   unsigned char opd4[8] = {
1297     0x06, 0xf4, 0xff, 0x81, 0x3d, 0x00, XXXX, XXXX
1298   };
1299   SANE_Status res;
1300 
1301   unsigned char *p;
1302   int h  = 66;
1303   int w  = color ? 3 * 5100 : 5100;
1304   int x0 = color ? 0 : 5100;
1305   int l  = w * h;
1306   int i, x, y;
1307 
1308   PAD_ARRAY (scan->caldata, 16070);
1309 
1310   DBG (9, "get_caldata: color = %d\n", color);
1311 
1312   p = malloc (l);
1313   if (p == 0)
1314     {
1315       DBG (1, "out of memory (need %d)\n", l);
1316       return SANE_STATUS_NO_MEM;
1317     }
1318   memset (scan->caldata, 0, 3 * 5100);
1319 
1320   CHK (csend (scan, CMD_0));
1321   opc9[0] = h + 4;
1322   if (color)
1323     {
1324       opc9[13]  = 0x03;
1325       opb11[23] = 0xc4;
1326       opb11[24] = 0x5c;
1327       opd4[6]   = 0x08;
1328       opd4[7]   = 0x00;
1329     }
1330   else
1331     {
1332       opc9[13]  = 0xc3;
1333       opb11[23] = 0xec;
1334       opb11[24] = 0x54;
1335       opd4[6]   = 0x0c;
1336       opd4[7]   = 0x40;
1337     }
1338 
1339   /* Do a test scan of the calibration strip (which is located
1340    * under the scanner's lid */
1341 
1342   CHK (get_pixels (scan, opc9, opb11, opd4, ope, l, 0, p));
1343 
1344 #ifdef DEBUG_CALIBRATION
1345   {
1346     FILE *f2 = fopen ("calibration.pgm", "wb");
1347     fprintf (f2, "P5\n%d %d\n255\n", w, h);
1348     fwrite (p, 1, w * h, f2);
1349     fclose (f2);
1350   }
1351 #endif
1352 
1353   scan->scanner_ypos += (h + 4) * 2 + 3;
1354   scan->scanner_ypos &= ~3;
1355 
1356   /* The following loop computes the gain for each of the CCD pixel
1357    * elements.
1358    */
1359   for (x = 0; x < w; ++x)
1360     {
1361       int t = 0, gn;
1362       double av, gain;
1363 
1364       for (y = 0; y < h; ++y)
1365         t += p[x + y * w];
1366       av = (double) t / h;
1367       gain = 250 / av;
1368       gn = (int) ((gain - 0.984) * 102.547 + 0.5);
1369       if (gn < 0)
1370         gn = 0;
1371       else if (gn > 255)
1372         gn = 255;
1373       scan->caldata[x + x0] = gn;
1374     }
1375 
1376   /* Gamma table for blue */
1377 
1378   for (i = 0; i < 256; ++i)
1379     scan->caldata[i + 3 * 5100 + 0] = i;
1380 
1381   /* Gamma table for green */
1382 
1383   for (i = 0; i < 256; ++i)
1384     scan->caldata[i + 3 * 5100 + 256] = i;
1385 
1386   /* Gamma table for red */
1387 
1388   for (i = 0; i < 256; ++i)
1389     scan->caldata[i + 3 * 5100 + 512] = i;
1390 
1391   free (p);
1392 
1393   CHK_ARRAY (scan->caldata, 16070);
1394   return SANE_STATUS_GOOD;
1395 }
1396 
1397 /* Calibration 2100U */
1398 
1399 /*
1400 Format of caldata:
1401 
1402    5100 bytes of CCD calibration values
1403    5100 bytes of CCD calibration values
1404    5100 bytes of CCD calibration values
1405    256 bytes of gamma data for blue
1406    256 bytes of gamma data for green
1407    256 bytes of gamma data for red
1408    2 bytes of extra information
1409 
1410 */
1411 static SANE_Status
get_caldata_2100U(UMAX_Handle * scan,int color)1412 get_caldata_2100U (UMAX_Handle * scan, int color)
1413 {
1414   unsigned char opc9[16] = {
1415     XXXX, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x15, 0x05,
1416     XXXX, XXXX, XXXX, XXXX, 0xac, 0x00
1417   };
1418   unsigned char opb11[36] = {
1419     0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04,
1420     0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, XXXX, XXXX, 0x46,
1421     0x06, 0x00, 0x00, XXXX, XXXX, 0xa0, 0x00, 0x8b, 0x49, 0x2a,
1422     0xe9, 0x68, 0xdf, 0x83, XXXX, 0x00
1423   };
1424   unsigned char opd4[8] = {
1425     0x06, 0xf4, 0xff, 0x81, 0x1b, 0x00, XXXX, XXXX
1426   };
1427   unsigned char ope[8] = {
1428     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
1429   };
1430 
1431 
1432 /* default gamma translation table */
1433   unsigned char ggamma[256] = {
1434     0x00, 0x06, 0x0A, 0x0D, 0x10, 0x12, 0x14, 0x17, 0x19, 0x1B, 0x1D,
1435     0x1F, 0x21, 0x23, 0x24, 0x26, 0x28, 0x2A, 0x2B, 0x2D, 0x2E, 0x30,
1436     0x31, 0x33, 0x34, 0x36, 0x37, 0x39, 0x3A, 0x3B, 0x3D, 0x3E, 0x40,
1437     0x41, 0x42, 0x43, 0x45, 0x46, 0x47, 0x49, 0x4A, 0x4B, 0x4C, 0x4D,
1438     0x4F, 0x50, 0x51, 0x52, 0x53, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
1439     0x5B, 0x5C, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
1440     0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
1441     0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
1442     0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x86,
1443     0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x90,
1444     0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x97, 0x98, 0x99, 0x9A,
1445     0x9B, 0x9C, 0x9D, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA2, 0xA3,
1446     0xA4, 0xA5, 0xA6, 0xA7, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAC,
1447     0xAD, 0xAE, 0xAF, 0xB0, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB4, 0xB5,
1448     0xB6, 0xB7, 0xB8, 0xB8, 0xB9, 0xBA, 0xBB, 0xBB, 0xBC, 0xBD, 0xBE,
1449     0xBF, 0xBF, 0xC0, 0xC1, 0xC2, 0xC2, 0xC3, 0xC4, 0xC5, 0xC5, 0xC6,
1450     0xC7, 0xC8, 0xC8, 0xC9, 0xCA, 0xCB, 0xCB, 0xCC, 0xCD, 0xCE, 0xCE,
1451     0xCF, 0xD0, 0xD1, 0xD1, 0xD2, 0xD3, 0xD4, 0xD4, 0xD5, 0xD6, 0xD6,
1452     0xD7, 0xD8, 0xD9, 0xD9, 0xDA, 0xDB, 0xDC, 0xDC, 0xDD, 0xDE, 0xDE,
1453     0xDF, 0xE0, 0xE1, 0xE1, 0xE2, 0xE3, 0xE3, 0xE4, 0xE5, 0xE6, 0xE6,
1454     0xE7, 0xE8, 0xE8, 0xE9, 0xEA, 0xEA, 0xEB, 0xEC, 0xEC, 0xED, 0xEE,
1455     0xEF, 0xEF, 0xF0, 0xF1, 0xF1, 0xF2, 0xF3, 0xF3, 0xF4, 0xF5, 0xF5,
1456     0xF6, 0xF7, 0xF7, 0xF8, 0xF9, 0xF9, 0xFA, 0xFB, 0xFB, 0xFC, 0xFD,
1457     0xFE, 0xFE, 0xFF
1458   };
1459 
1460 
1461   SANE_Status res;
1462 
1463   unsigned char *p;
1464   int h  = 66;
1465   int w  = color ? 3 * 5100 : 5100;
1466   int x0 = color ? 0 : 5100;
1467   int l  = w * h;
1468   int i, x, y;
1469   int t, gn;
1470   double av, pct;
1471 
1472   PAD_ARRAY (scan->caldata, 16070);
1473 
1474   DBG (9, "get_caldata: color = %d\n", color);
1475 
1476   p = malloc (l);
1477   if (p == 0)
1478     {
1479       DBG (1, "out of memory (need %d)\n", l);
1480       return SANE_STATUS_NO_MEM;
1481     }
1482   memset (scan->caldata, 0, 3 * 5100);
1483 
1484   CHK (csend (scan, CMD_0));
1485   CHK (csend (scan, CMD_0));
1486 
1487   opc9[0] = h + 4;
1488 
1489   if (color)
1490     {
1491       opc9[10]  = 0xb6;
1492       opc9[11]  = 0x3b;
1493       opc9[12]  = 0x0c;
1494       opc9[13]  = 0x03;
1495       opb11[17] = 0x7e;
1496       opb11[18] = 0xb0;
1497       opb11[23] = 0xc4;
1498       opb11[24] = 0x5c;
1499       opb11[34] = 0x1b;
1500       opd4[6]   = 0x0f;
1501       opd4[7]   = 0x40;
1502     }
1503   else
1504     {
1505       opc9[10]  = 0xa6;
1506       opc9[11]  = 0x2a;
1507       opc9[12]  = 0x08;
1508       opc9[13]  = 0xc2;
1509       opb11[17] = 0x7f;
1510       opb11[18] = 0xc0;
1511       opb11[23] = 0xec;
1512       opb11[24] = 0x54;
1513       opb11[34] = 0x1a;
1514       opd4[6]   = 0x06;
1515       opd4[7]   = 0x20;
1516     }
1517 
1518   /* Do a test scan of the calibration strip (which is located
1519    * under the scanner's lid */
1520   CHK (get_pixels_2100U (scan, opc9, opb11, opd4, ope, l, 0, p));
1521 
1522 #ifdef DEBUG_CALIBRATION
1523   {
1524     FILE *f2 = fopen ("calibration.pgm", "wb");
1525     fprintf (f2, "P5\n%d %d\n255\n", w, h);
1526     fwrite (p, 1, w * h, f2);
1527     fclose (f2);
1528   }
1529 #endif
1530 
1531   scan->scanner_ypos += (h + 4) * 2 + 3;
1532   scan->scanner_ypos &= ~3;
1533 
1534   /* The following loop computes the gain for each of the CCD pixel
1535    * elements.
1536    */
1537   for (x = 0; x < w; x++)
1538     {
1539       t = 0;
1540       for (y = 0; y < h; y++)
1541         t += p[x + y * w];
1542       av = (double) t / h;
1543       pct = 100.0 - (av * 100.0) / 250;
1544       gn = (int) (pct / 0.57);
1545 
1546       pct = gn;
1547       av = exp((-pct)/50)*2.5+0.9;
1548       gn = gn * av;
1549 
1550 
1551       if (gn < 0)
1552         gn = 0;
1553       else if (gn > 127)
1554         gn = 127;
1555       scan->caldata[x + x0] = gn;
1556     }
1557 
1558   /* Gamma table for blue */
1559 
1560   for (i = 0; i < 256; i++)
1561     scan->caldata[i + 3 * 5100 + 0] = ggamma[i];
1562 
1563   /* Gamma table for green */
1564 
1565   for (i = 0; i < 256; i++)
1566     scan->caldata[i + 3 * 5100 + 256] = ggamma[i];
1567 
1568   /* Gamma table for red */
1569 
1570   for (i = 0; i < 256; i++)
1571     scan->caldata[i + 3 * 5100 + 512] = ggamma[i];
1572 
1573   free (p);
1574 
1575   CHK_ARRAY (scan->caldata, 16070);
1576   return SANE_STATUS_GOOD;
1577 }
1578 
1579 
1580 
1581 /* Sends scan user parameters from frontend 1220U */
1582 
1583 static SANE_Status
send_scan_parameters(UMAX_Handle * scan)1584 send_scan_parameters (UMAX_Handle * scan)
1585 {
1586   SANE_Status res;
1587   UMAX_Status_Byte s;
1588 
1589   /* Appears to correspond to opscan in umax_pp_low.c */
1590   unsigned char opbgo[35] = {
1591     0x00, 0x00, 0xb0, 0x4f, 0xd8, 0xe7, 0xfa, 0x10, 0xef, 0xc4,
1592     0x3c, 0x71, 0x0f, 0x00, 0x04, 0x00, 0x6e, XXXX, XXXX, XXXX,
1593     0xc4, 0x7e, 0x00, XXXX, XXXX, 0xa0, 0x0a, 0x8b, 0x49, 0x4a,
1594     0xd0, 0x68, 0xdf, XXXX, 0x1a
1595   };
1596 
1597   /* Appears to correspond to opsc53 in umax_pp_low.c */
1598   unsigned char opcgo[16] = {
1599     XXXX, XXXX, XXXX, XXXX, 0xec, 0x03, XXXX, XXXX, XXXX, XXXX,
1600     0xec, 0x4e, XXXX, XXXX, XXXX
1601   };
1602 
1603   /* Appears to correspond to opsc04 in umax_pp_low.c */
1604   unsigned char opdgo[8] = {
1605     0x06, 0xf4, 0xff, 0x81, 0x3d, 0x00, XXXX, XXXX
1606   };
1607 
1608   unsigned char subsamp[9] = {
1609     0xff, 0xff, 0xaa, 0xaa, 0x88, 0x88, 0x88, 0x88, 0x80
1610   };
1611 
1612   const int xend =
1613     scan->xskip + scan->w * scan->xsamp + (scan->xsamp + 1) / 2;
1614   const int ytot = scan->hexp * scan->ysamp + 12;
1615 
1616   opbgo[17] = scan->xskip % 256;
1617   opbgo[18] = ((scan->xskip >> 8) & 0xf) + (xend << 4);
1618   opbgo[19] = xend >> 4;
1619   opbgo[33] = 0x33 + ((xend & 0x1000) >> 5) + ((scan->xskip & 0x1000) >> 6);
1620 
1621   /* bytes per line */
1622 
1623   opbgo[23] = scan->color ? 0xc6 : 0x77;
1624   opbgo[24] = scan->color ? 0x5b : 0x4a;
1625 
1626   /* Scan height */
1627 
1628   opcgo[0] = ytot;
1629   opcgo[1] = ((ytot >> 8) & 0x3f) + (scan->yskip << 6);
1630   opcgo[2] = scan->yskip >> 2;
1631   opcgo[3] = 0x50 + ((scan->yskip >> 10) & 0xf);
1632 
1633   /* This is what used to be here:
1634 
1635      opcgo[6] = bh == h? 0: 0x60;       // a guess
1636 
1637      I replaced it with what umax_pp_low.c uses, since it
1638      made more sense
1639    */
1640   opcgo[6]  = (scan->ydpi <= 300) ? 0x00 : 0x60;
1641   opcgo[8]  = (scan->ydpi <= 300) ? 0x17 : 0x2F;
1642   opcgo[9]  = (scan->ydpi >= 300) ? 0x05 : 0x07;
1643   opcgo[14] = (scan->ydpi == 600) ? 0xa4 : 0xac;
1644 
1645   opcgo[7]  = scan->color ? 0x2F : 0x40;
1646   opcgo[12] = scan->color ? 0x10 : 0x0C;
1647   opcgo[13] = scan->color ? 0x04 : 0xc3;
1648 
1649   opdgo[6]  = scan->color ? 0x88 : 0x8c;
1650   opdgo[7]  = scan->color ? 0x00 : 0x40;
1651 
1652   DBG (3, "send_scan_parameters: xskip = %d, yskip = %d\n", scan->xskip,
1653        scan->yskip);
1654 
1655   CHK (csend (scan, CMD_0));
1656   CHK (csend (scan, CMD_0));
1657   CHK (cwritev (scan, CMD_2, 16, opcgo, &s));
1658   CHK (cwritev (scan, CMD_8, 35, opbgo, &s));
1659   CHK (cwritev (scan, CMD_1, 8, opdgo, &s));
1660   CHK (cread (scan, CMD_2, 0, NULL, &s));
1661   DBG (4, "send_scan_parameters: checkpoint 1: s = %d\n", s);
1662 
1663   /* Loads the new calibration data (that was computed by get_caldata) into the
1664      scanner */
1665 
1666   scan->caldata[16068] = subsamp[scan->xsamp];
1667   scan->caldata[16069] = subsamp[scan->ysamp];
1668   CHK (cwrite (scan, CMD_4, 16070, scan->caldata, &s));
1669 
1670   CHK (csend (scan, CMD_40));
1671   CHK (cread (scan, CMD_2, 0, NULL, &s));
1672 
1673   DBG (4, "send_scan_parameters: checkpoint 2: s = %d\n", s);
1674 
1675   return SANE_STATUS_GOOD;
1676 }
1677 
1678 /* Sends scan user parameters from frontend 2100U */
1679 
1680 static SANE_Status
send_scan_parameters_2100U(UMAX_Handle * scan)1681 send_scan_parameters_2100U (UMAX_Handle * scan)
1682 {
1683   SANE_Status res;
1684   UMAX_Status_Byte s;
1685   int bpl;
1686 
1687   /* Appears to correspond to opscan in umax_pp_low.c */
1688   unsigned char opbgo[36] = {
1689     0x00, 0x00, 0xb0, 0x4f, 0xd8, 0xe7, 0xfa, 0x10, 0xef, 0xc4,
1690     0x3c, 0x71, 0x0f, 0x00, 0x04, 0x00, 0x6e, XXXX, XXXX, XXXX,
1691     0xc4, 0x7e, 0x00, XXXX, XXXX, 0xa0, 0x0a, 0x8b, 0x49, 0x2a,
1692     0xe9, 0x68, 0xdf, XXXX, 0x1a, 0x00
1693   };
1694 
1695   /* Appears to correspond to opsc53 in umax_pp_low.c */
1696   unsigned char opcgo[16] = {
1697     XXXX, XXXX, XXXX, XXXX, 0xec, 0x03, 0x60, XXXX, XXXX, XXXX,
1698     XXXX, XXXX, XXXX, XXXX, XXXX, 0x00
1699   };
1700 
1701   /* Appears to correspond to opsc04 in umax_pp_low.c */
1702   unsigned char opdgo[8] = {
1703     0x06, 0xf4, 0xff, 0x81, 0x1b, 0x00, XXXX, XXXX
1704   };
1705 
1706   unsigned char subsamp[9] = {
1707     0xff, 0xff, 0xaa, 0xaa, 0x88, 0x88, 0x88, 0x88, 0x80
1708   };
1709 
1710   const int xend =
1711     scan->xskip + scan->w * scan->xsamp + (scan->xsamp + 1) / 2;
1712   const int ytot = scan->hexp * scan->ysamp + 12;
1713 
1714   opbgo[17] = scan->xskip % 256;
1715   opbgo[18] = ((scan->xskip >> 8) & 0x0f) + (xend << 4);
1716   opbgo[19] = xend >> 4;
1717   opbgo[33] = 0x23 + ((xend & 0x1000) >> 5) + ((scan->xskip & 0x1000) >> 6);
1718 
1719   /* bytes per line */
1720 
1721   bpl = (scan->color ? 3 : 1) * scan->w * scan->xdpi;
1722   opbgo[23] = bpl % 256;
1723   opbgo[24] = 0x41 + ((bpl / 256) & 0x1f);
1724 
1725   /* Scan height */
1726 
1727   opcgo[0] = ytot;
1728   opcgo[1] = ((ytot >> 8) & 0x3f) + (scan->yskip << 6);
1729   opcgo[2] = (scan->yskip >> 2);
1730   opcgo[3] = 0x50 + ((scan->yskip >> 10) & 0x0f);
1731 
1732 
1733   opcgo[6]  = (scan->ydpi <= 300) ? 0x00 : 0x60;
1734   opcgo[8]  = (scan->ydpi <= 300) ? 0x17 : 0x2F;
1735   opcgo[9]  = (scan->ydpi >= 300) ? 0x05 : 0x07;
1736   opcgo[14] = (scan->ydpi == 600) ? 0xa4 : 0xac;
1737 
1738 
1739   opcgo[7]  = scan->color ? 0x2f : 0x40;
1740   opcgo[10] = scan->color ? 0xb6 : 0xa6;
1741   opcgo[11] = scan->color ? 0x3b : 0x2a;
1742   opcgo[12] = scan->color ? 0x0c : 0x08;
1743   opcgo[13] = scan->color ? 0x03 : 0xc2;
1744 
1745   opdgo[6]  = scan->color ? 0x8f : 0x86;
1746   opdgo[7]  = scan->color ? 0x40 : 0x20;
1747 
1748   DBG (3, "send_scan_parameters: xskip = %d, yskip = %d\n", scan->xskip,
1749        scan->yskip);
1750 
1751   CHK (csend (scan, CMD_0));
1752   CHK (csend (scan, CMD_0));
1753   CHK (cwritev (scan, CMD_2, 16, opcgo, &s));
1754   CHK (cwritev (scan, CMD_8, 36, opbgo, &s));
1755   CHK (cwritev (scan, CMD_1, 8, opdgo, &s));
1756   CHK (cread (scan, CMD_2, 0, NULL, &s));
1757   DBG (4, "send_scan_parameters: checkpoint 1: s = %d\n", s);
1758 
1759   /* Loads the new calibration data (that was computed by get_caldata) into the
1760      scanner */
1761 
1762   scan->caldata[16068] = subsamp[scan->xsamp];
1763   scan->caldata[16069] = subsamp[scan->ysamp];
1764   CHK (cwrite (scan, CMD_4, 16070, scan->caldata, &s));
1765 
1766   CHK (csend (scan, CMD_40));
1767   CHK (cread (scan, CMD_2, 0, NULL, &s));
1768 
1769   DBG (4, "send_scan_parameters: checkpoint 2: s = %d\n", s);
1770 
1771   return SANE_STATUS_GOOD;
1772 }
1773 
1774 /* Read raw data */
1775 
1776 static SANE_Status
read_raw_data(UMAX_Handle * scan,unsigned char * data,int len)1777 read_raw_data (UMAX_Handle * scan, unsigned char *data, int len)
1778 {
1779   SANE_Status res;
1780   UMAX_Status_Byte s;
1781 
1782   CHK (cread (scan, CMD_2, 0, NULL, &s));
1783   CHK (cread (scan, CMD_4, len, data, &s));
1784 
1785   return SANE_STATUS_GOOD;
1786 }
1787 
1788 /* Read raw strip color */
1789 
1790 static SANE_Status
read_raw_strip_color(UMAX_Handle * scan)1791 read_raw_strip_color (UMAX_Handle * scan)
1792 {
1793   /**
1794      yres = 75   => ydpi = 150 => ysamp = 2 => yoff_scale = 8
1795      yres = 150  => ydpi = 150 => ysamp = 1 => yoff_scale = 4
1796      yres = 300  => ydpi = 300 => ysamp = 1 => yoff_scale = 2
1797      yres = 600  => ydpi = 600 => ysamp = 1 => yoff_scale = 1
1798   */
1799 
1800   const int yoff_scale = 600 * scan->ysamp / scan->ydpi;
1801   const int linelen = 3 * scan->w;
1802 
1803   /*
1804      yoff_scale = 8  =>  roff = 5  * w,  goff = 1  * w,  boff = 0 * w, hextra = 1
1805      yoff_scale = 4  =>  roff = 8  * w,  goff = 4  * w,  boff = 0 * w, hextra = 2
1806      yoff_scale = 2  =>  roff = 14 * w,  goff = 7  * w,  boff = 0 * w, hextra = 4
1807      yoff_scale = 1  =>  roff = 26 * w,  goff = 13 * w,  boff = 0 * w, hextra = 8
1808    */
1809 
1810   const int hextra = 8 / yoff_scale;
1811 
1812   SANE_Status res;
1813   int lines_to_read = scan->hexp;
1814 
1815   DBG (9, "read_raw_strip_color: hexp = %d, bh = %d\n", scan->hexp, scan->bh);
1816 
1817   if (scan->maxh == -1)
1818     {
1819       DBG (10, "read_raw_strip_color: filling buffer for the first time\n");
1820       if (lines_to_read > scan->bh)
1821         lines_to_read = scan->bh;
1822 
1823       CHK (read_raw_data (scan, scan->p, lines_to_read * linelen));
1824       scan->maxh = lines_to_read - hextra;
1825     }
1826   else
1827     {
1828       DBG (10, "read_raw_strip_color: reading new rows into buffer\n");
1829       memmove (scan->p, scan->p + (scan->bh - hextra) * linelen,
1830                hextra * linelen);
1831 
1832       if (lines_to_read > (scan->bh - hextra))
1833         lines_to_read = scan->bh - hextra;
1834 
1835       CHK (read_raw_data
1836            (scan, scan->p + hextra * linelen, lines_to_read * linelen));
1837       scan->maxh = lines_to_read;
1838     }
1839 
1840   scan->hexp -= lines_to_read;
1841   scan->x = 0;
1842   scan->y = 0;
1843 
1844   return SANE_STATUS_GOOD;
1845 }
1846 
1847 /* Read raw strip grey */
1848 
1849 static SANE_Status
read_raw_strip_gray(UMAX_Handle * scan)1850 read_raw_strip_gray (UMAX_Handle * scan)
1851 {
1852   const int linelen = scan->w;
1853 
1854   SANE_Status res;
1855 
1856   int lines_to_read = scan->bh;
1857 
1858   DBG (9, "read_raw_strip_gray: hexp = %d\n", scan->hexp);
1859 
1860   if (lines_to_read > scan->hexp)
1861     lines_to_read = scan->hexp;
1862   scan->hexp -= lines_to_read;
1863 
1864   CHK (read_raw_data (scan, scan->p, lines_to_read * linelen));
1865 
1866   scan->maxh = lines_to_read;
1867   scan->x = 0;
1868   scan->y = 0;
1869 
1870   return SANE_STATUS_GOOD;
1871 }
1872 
1873 
1874 /* Read raw strip */
1875 
1876 static SANE_Status
read_raw_strip(UMAX_Handle * scan)1877 read_raw_strip (UMAX_Handle * scan)
1878 {
1879   if (scan->color)
1880       return read_raw_strip_color (scan);
1881   else
1882       return read_raw_strip_gray (scan);
1883 }
1884 
1885 /* Set scan user pamaters Frontend */
1886 
1887 static SANE_Status
UMAX_set_scan_parameters(UMAX_Handle * scan,const int color,const int xo,const int yo,const int w,const int h,const int xres,const int yres)1888 UMAX_set_scan_parameters (UMAX_Handle * scan,
1889                           const int color,
1890                           const int xo,
1891                           const int yo,
1892                           const int w,
1893                           const int h, const int xres, const int yres)
1894 {
1895 
1896   /* Validate the input parameters */
1897 
1898   int left = xo;
1899   int top = yo;
1900   int right = xo + w * 600 / xres;
1901   int bottom = yo + h * 600 / yres;
1902 
1903   DBG (2, "UMAX_set_scan_parameters:\n");
1904   DBG (2, "color = %d             \n", color);
1905   DBG (2, "xo    = %d, yo     = %d\n", xo, yo);
1906   DBG (2, "w     = %d, h      = %d\n", w, h);
1907   DBG (2, "xres  = %d, yres   = %d\n", xres, yres);
1908   DBG (2, "left  = %d, top    = %d\n", left, top);
1909   DBG (2, "right = %d, bottom = %d\n", right, bottom);
1910 
1911   if ((left < 0) || (right > UMAX_MAX_WIDTH))
1912     return SANE_STATUS_INVAL;
1913 
1914   if ((top < 0) || (bottom > UMAX_MAX_HEIGHT))
1915     return SANE_STATUS_INVAL;
1916 
1917   if (((right - left) < 10) || ((bottom - top) < 10))
1918     return SANE_STATUS_INVAL;
1919 
1920   if ((xres != 75) && (xres != 150) && (xres != 300) && (xres != 600))
1921     return SANE_STATUS_INVAL;
1922 
1923   if ((yres != 75) && (yres != 150) && (yres != 300) && (yres != 600))
1924     return SANE_STATUS_INVAL;
1925 
1926   /* If we get this far, begin initializing the data
1927      structure
1928    */
1929 
1930   scan->color = color;
1931   scan->w = w;
1932   scan->h = h;
1933   scan->xo = xo;
1934   scan->yo = yo;
1935 
1936   /*
1937      The scanner has a fixed X resolution of 600 dpi, but
1938      supports three choices for the Y resolution. We must
1939      choose an appropriate physical resolution and the
1940      corresponding sampling value.
1941 
1942      It is not clear to me why the choice depends on
1943      whether we are scanning in color or not, but the
1944      original code did this and I didn't want to mess
1945      with it.
1946 
1947      Physical X resolution choice:
1948      xres = 75   =>  xdpi = 600  (xsamp = 8)
1949      xres = 150  =>  xdpi = 600  (xsamp = 4)
1950      xres = 300  =>  xdpi = 600  (xsamp = 2)
1951      xres = 600  =>  xdpi = 600  (xsamp = 1)
1952 
1953      Physical Y resolution choice (if color):
1954      yres = 75    =>  ydpi = 150  (ysamp = 2)
1955      yres = 150   =>  ydpi = 150  (ysamp = 1)
1956      yres = 300   =>  ydpi = 300  (ysamp = 1)
1957      yres = 600   =>  ydpi = 600  (ysamp = 1)
1958 
1959      Physical Y resolution choice (if not color):
1960      yres = 75    =>  ydpi = 300  (ysamp = 4)
1961      yres = 150   =>  ydpi = 300  (ysamp = 2)
1962      yres = 300   =>  ydpi = 300  (ysamp = 1)
1963      yres = 600   =>  ydpi = 600  (ysamp = 1)
1964    */
1965 
1966   scan->xdpi = 600;
1967   if (yres <= 150 && color)
1968     scan->ydpi = 150;
1969   else if (yres > 300)
1970     scan->ydpi = 600;
1971   else
1972     scan->ydpi = 300;
1973 
1974   scan->xsamp = scan->xdpi / xres;
1975   scan->ysamp = scan->ydpi / yres;
1976 
1977   return SANE_STATUS_GOOD;
1978 }
1979 
1980 /* Start actual scan 1220U */
1981 
1982 static SANE_Status
UMAX_start_scan(UMAX_Handle * scan)1983 UMAX_start_scan (UMAX_Handle * scan)
1984 {
1985   SANE_Status res;
1986   int linelen;
1987   int yd;
1988 
1989   DBG (3, "UMAX_start_scan called\n");
1990 
1991   if (scan->color)
1992     {
1993       const int yoff_scale = 600 * scan->ysamp / scan->ydpi;
1994       const int hextra = 8 / yoff_scale;
1995 
1996       linelen = 3 * scan->w;
1997       scan->hexp = scan->h + hextra;
1998     }
1999   else
2000     {
2001       linelen = scan->w;
2002       scan->hexp = scan->h;
2003     }
2004 
2005   scan->bh = BUFFER_SIZE / linelen;
2006 
2007   scan->p = malloc (scan->bh * linelen);
2008   if (scan->p == 0)
2009     return SANE_STATUS_NO_MEM;
2010 
2011   DBG (4, "UMAX_start_scan: bh = %d, linelen = %d\n", scan->bh, linelen);
2012 
2013   scan->maxh = -1;
2014   scan->done = 0;
2015 
2016   /* Initialize the scanner and position the scan head */
2017 
2018   CHK (umaxinit (scan));
2019 
2020   /* This scans in the black and white calibration strip that
2021    * is located under the scanner's lid. The scan of that strip
2022    * is used to pick correct values for the CCD calibration
2023    * values
2024    */
2025 
2026   scan->scanner_ypos = 0;
2027   CHK (move (scan, 196, UMAX_NOT_FINE));
2028   CHK (find_zero (scan));
2029   CHK (move (scan, scan->scanner_yorg - 232 - scan->scanner_ypos, UMAX_FINE));
2030   CHK (get_caldata (scan, scan->color));
2031 
2032   /* This moves the head back to the starting position */
2033 
2034   yd = scan->scanner_yorg + scan->yo - scan->scanner_ypos;
2035   if (yd < 0)
2036     CHK (move (scan, yd, UMAX_FINE));
2037   if (yd > 300)
2038     CHK (move (scan, (yd - 20) / 2, UMAX_NOT_FINE));
2039   yd = scan->scanner_yorg + scan->yo - scan->scanner_ypos;
2040 
2041   scan->yskip = yd / (600 / scan->ydpi);
2042   scan->xskip = scan->xo / (600 / scan->xdpi);
2043 
2044   /* Read in the first chunk of raw data */
2045 
2046   CHK (send_scan_parameters (scan));
2047   CHK (read_raw_strip (scan));
2048 
2049   DBG (4, "UMAX_start_scan successful\n");
2050 
2051   return SANE_STATUS_GOOD;
2052 }
2053 
2054 
2055 /* Start actual scan 2100U */
2056 
2057 static SANE_Status
UMAX_start_scan_2100U(UMAX_Handle * scan)2058 UMAX_start_scan_2100U (UMAX_Handle * scan)
2059 {
2060   SANE_Status res;
2061   int linelen;
2062   int yd;
2063 
2064   DBG (3, "UMAX_start_scan called\n");
2065 
2066   if (scan->color)
2067     {
2068       const int yoff_scale = 600 * scan->ysamp / scan->ydpi;
2069       const int hextra = 8 / yoff_scale;
2070 
2071       linelen = 3 * scan->w;
2072       scan->hexp = scan->h + hextra;
2073     }
2074   else
2075     {
2076       linelen = scan->w;
2077       scan->hexp = scan->h;
2078     }
2079 
2080   scan->bh = BUFFER_SIZE / linelen;
2081 
2082   scan->p = malloc (scan->bh * linelen);
2083   if (scan->p == 0)
2084     return SANE_STATUS_NO_MEM;
2085 
2086   DBG (4, "UMAX_start_scan: bh = %d, linelen = %d\n", scan->bh, linelen);
2087 
2088   scan->maxh = -1;
2089   scan->done = 0;
2090 
2091   /* Initialize the scanner and position the scan head */
2092 
2093   CHK (umaxinit_2100U (scan));
2094 
2095   /* This scans in the black and white calibration strip that
2096    * is located under the scanner's lid. The scan of that strip
2097    * is used to pick correct values for the CCD calibration
2098    * values
2099    */
2100 
2101   scan->scanner_ypos = 0;
2102   CHK (move_2100U (scan, 196, UMAX_NOT_FINE));
2103   CHK (find_zero_2100U (scan));
2104   CHK (move_2100U (scan, scan->scanner_yorg - 232 - scan->scanner_ypos, UMAX_FINE));
2105   CHK (get_caldata_2100U (scan, scan->color));
2106 
2107   /* This moves the head back to the starting position */
2108 
2109   yd = scan->scanner_yorg + scan->yo - scan->scanner_ypos;
2110   if (yd < 0)
2111     CHK (move_2100U (scan, yd, UMAX_FINE));
2112   if (yd > 300)
2113     CHK (move_2100U (scan, (yd - 20) / 2, UMAX_NOT_FINE));
2114   yd = scan->scanner_yorg + scan->yo - scan->scanner_ypos;
2115 
2116   scan->yskip = yd / (600 / scan->ydpi);
2117   scan->xskip = scan->xo / (600 / scan->xdpi);
2118 
2119   /* Read in the first chunk of raw data */
2120 
2121   CHK (send_scan_parameters_2100U (scan));
2122   CHK (read_raw_strip (scan));
2123 
2124   DBG (4, "UMAX_start_scan successful\n");
2125 
2126   return SANE_STATUS_GOOD;
2127 }
2128 
2129 /* Set lamp state */
2130 
2131 static SANE_Status
UMAX_set_lamp_state(UMAX_Handle * scan,UMAX_Lamp_State state)2132 UMAX_set_lamp_state (UMAX_Handle * scan, UMAX_Lamp_State state)
2133 {
2134   SANE_Status res;
2135 
2136   DBG (3, "UMAX_set_lamp_state: state = %d\n", (int) state);
2137 
2138   CHK (csend (scan, CMD_0));
2139   CHK (cwritev_opc1_lamp_ctrl (scan, state));
2140   return SANE_STATUS_GOOD;
2141 }
2142 
2143 /* Park head 1220U */
2144 
2145 static SANE_Status
UMAX_park_head(UMAX_Handle * scan)2146 UMAX_park_head (UMAX_Handle * scan)
2147 {
2148   SANE_Status res;
2149   UMAX_Status_Byte s;
2150   int i;
2151 
2152   DBG (3, "UMAX_park_head called\n");
2153 
2154   CHK (csend (scan, CMD_0));
2155   /* WARNING: Must call cwritev_opc1_lamp_ctrl before cwritev_opb3_restore,
2156    * otherwise the head moves the wrong way and makes ugly grinding noises. */
2157 
2158   CHK (cwritev_opc1_lamp_ctrl (scan, UMAX_LAMP_ON));
2159   CHK (cwritev_opb3_restore (scan));
2160 
2161   for (i = 0; i < 60; ++i)
2162     {
2163       CHK (cread (scan, CMD_2, 0, NULL, &s));
2164       DBG (4, "UMAX_park_head: s = %#x\n", s);
2165       if ((s & 0x40) != 0)
2166         break;
2167       DBG (4, "UMAX_park_head: sleeping\n");
2168       usleep (500000);
2169     }
2170 
2171   scan->scanner_ypos = 0;
2172 
2173   return SANE_STATUS_GOOD;
2174 }
2175 
2176 
2177 /* Park head 2100U */
2178 
2179 static SANE_Status
UMAX_park_head_2100U(UMAX_Handle * scan)2180 UMAX_park_head_2100U (UMAX_Handle * scan)
2181 {
2182   SANE_Status res;
2183   UMAX_Status_Byte s;
2184   int i;
2185 
2186   DBG (3, "UMAX_park_head called\n");
2187 
2188   CHK (csend (scan, CMD_0));
2189   /* WARNING: Must call cwritev_opc1_lamp_ctrl before cwritev_opb3_restore,
2190    * otherwise the head moves the wrong way and makes ugly grinding noises. */
2191 
2192   CHK (cwritev_opc1_lamp_ctrl (scan, UMAX_LAMP_ON));
2193   CHK (cwritev_opb3_restore_2100U (scan));
2194 
2195   for (i = 0; i < 60; ++i)
2196     {
2197       CHK (cread (scan, CMD_2, 0, NULL, &s));
2198       DBG (4, "UMAX_park_head: s = %#x\n", s);
2199       if ((s & 0x40) != 0)
2200         break;
2201       DBG (4, "UMAX_park_head: sleeping\n");
2202       usleep (500000);
2203     }
2204 
2205   /* CHK (csend (scan, CMD_0));
2206   CHK (csend (scan, CMD_0)); */
2207 
2208   scan->scanner_ypos = 0;
2209 
2210   return SANE_STATUS_GOOD;
2211 }
2212 
2213 
2214 /* Finish scan */
2215 
2216 static SANE_Status
UMAX_finish_scan(UMAX_Handle * scan)2217 UMAX_finish_scan (UMAX_Handle * scan)
2218 {
2219   DBG (3, "UMAX_finish_scan:\n");
2220 
2221   if (scan->p)
2222     free (scan->p);
2223   scan->p = NULL;
2224   return SANE_STATUS_GOOD;
2225 }
2226 
2227 
2228 /* RGB decoding for a color scan */
2229 
2230 static SANE_Status
UMAX_get_rgb(UMAX_Handle * scan,unsigned char * rgb)2231 UMAX_get_rgb (UMAX_Handle * scan, unsigned char *rgb)
2232 {
2233 
2234   if (scan->color)
2235     {
2236       const int linelen = 3 * scan->w;
2237       const int yoff_scale = 600 * scan->ysamp / scan->ydpi;
2238       const int roff = (8 / yoff_scale * 3 + 2) * scan->w;
2239       const int goff = (4 / yoff_scale * 3 + 1) * scan->w;
2240       const int boff = 0;
2241 
2242       unsigned char *base = scan->p + (scan->y * linelen) + scan->x;
2243 
2244       rgb[0] = base[roff];
2245       rgb[1] = base[goff];
2246       rgb[2] = base[boff];
2247     }
2248   else
2249     {
2250       const int linelen = scan->w;
2251       unsigned char *base = scan->p + (scan->y * linelen) + (scan->x);
2252 
2253       rgb[0] = base[0];
2254       rgb[1] = base[0];
2255       rgb[2] = base[0];
2256     }
2257 
2258   if (!(((scan->x + 1) == scan->w) && ((scan->y + 1) == scan->maxh)))
2259     {
2260       ++scan->x;
2261       if (scan->x == scan->w)
2262         {
2263           ++scan->y;
2264           scan->x = 0;
2265         }
2266       return SANE_STATUS_GOOD;
2267     }
2268 
2269   if (scan->hexp <= 0)
2270     {
2271       DBG (4, "UMAX_get_rgb: setting done flag\n");
2272       scan->done = 1;
2273       return SANE_STATUS_GOOD;
2274     }
2275 
2276   return read_raw_strip (scan);
2277 }
2278 
2279 /* Close device */
2280 
2281 static SANE_Status
UMAX_close_device(UMAX_Handle * scan)2282 UMAX_close_device (UMAX_Handle * scan)
2283 {
2284   DBG (3, "UMAX_close_device:\n");
2285   sanei_usb_close (scan->fd);
2286   return SANE_STATUS_GOOD;
2287 }
2288 
2289 /* Open device */
2290 
2291 static SANE_Status
UMAX_open_device(UMAX_Handle * scan,const char * dev)2292 UMAX_open_device (UMAX_Handle * scan, const char *dev)
2293 {
2294   SANE_Word vendor;
2295   SANE_Word product;
2296   SANE_Status res;
2297 
2298   DBG (3, "UMAX_open_device: `%s'\n", dev);
2299 
2300   res = sanei_usb_open (dev, &scan->fd);
2301   if (res != SANE_STATUS_GOOD)
2302     {
2303       DBG (1, "UMAX_open_device: couldn't open device `%s': %s\n", dev,
2304            sane_strstatus (res));
2305       return res;
2306     }
2307 
2308 #ifndef NO_AUTODETECT
2309   /* We have opened the device. Check that it is a USB scanner. */
2310   if (sanei_usb_get_vendor_product (scan->fd, &vendor, &product) !=
2311       SANE_STATUS_GOOD)
2312     {
2313       DBG (1, "UMAX_open_device: sanei_usb_get_vendor_product failed\n");
2314       /* This is not a USB scanner, or SANE or the OS doesn't support it. */
2315       sanei_usb_close (scan->fd);
2316       scan->fd = -1;
2317       return SANE_STATUS_UNSUPPORTED;
2318     }
2319 
2320   /* Make sure we have a UMAX scanner */
2321   if (vendor != 0x1606)
2322     {
2323       DBG (1, "UMAX_open_device: incorrect vendor\n");
2324       sanei_usb_close (scan->fd);
2325       scan->fd = -1;
2326       return SANE_STATUS_UNSUPPORTED;
2327     }
2328 
2329   /* Now check whether it is a scanner we know about */
2330   switch (product)
2331     {
2332     case ASTRA_2000U:
2333       /* The UMAX Astra 2000U is only partially supported by
2334          this driver. Expect severe color problems! :)
2335        */
2336       DBG (1,
2337            "UMAX_open_device: Scanner is a 2000U. Expect color problems :)\n");
2338       scan->model = ASTRA_2000U;
2339       break;
2340      case ASTRA_2100U:
2341        scan->model = ASTRA_2100U;
2342       break;
2343     case ASTRA_1220U:
2344        scan->model = ASTRA_1220U;
2345       break;
2346     default:
2347       DBG (1, "UMAX_open_device: unknown product number\n");
2348       sanei_usb_close (scan->fd);
2349       scan->fd = -1;
2350       return SANE_STATUS_UNSUPPORTED;
2351     }
2352 #endif
2353 
2354   res = csend (scan, CMD_0);
2355   if (res != SANE_STATUS_GOOD)
2356     UMAX_close_device (scan);
2357   CHK (res);
2358 
2359   res = xxxops (scan);
2360   if (res != SANE_STATUS_GOOD)
2361     UMAX_close_device (scan);
2362   CHK (res);
2363 
2364   return SANE_STATUS_GOOD;
2365 }
2366 
2367 /* Get scanner model name */
2368 
2369 static const char *
UMAX_get_device_name(UMAX_Handle * scan)2370 UMAX_get_device_name (UMAX_Handle * scan)
2371 {
2372   switch (scan->model)
2373     {
2374     case ASTRA_1220U:
2375       return "Astra 1220U";
2376     case ASTRA_2000U:
2377       return "Astra 2000U";
2378     case ASTRA_2100U:
2379       return "Astra 2100U";
2380     }
2381   return "Unknown";
2382 }
2383 
2384 /* End */
2385