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