1 /* lexmark-low.c: scanner-interface file for low Lexmark scanners.
2
3 (C) 2005 Fred Odendaal
4 (C) 2006-2013 Stéphane Voltz <stef.dev@free.fr>
5 (C) 2010 "Torsten Houwaart" <ToHo@gmx.de> X74 support
6
7 This file is part of the SANE package.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <https://www.gnu.org/licenses/>.
21
22 As a special exception, the authors of SANE give permission for
23 additional uses of the libraries contained in this release of SANE.
24
25 The exception is that, if you link a SANE library with other files
26 to produce an executable, this does not by itself cause the
27 resulting executable to be covered by the GNU General Public
28 License. Your use of that executable is in no way restricted on
29 account of linking the SANE library code into it.
30
31 This exception does not, however, invalidate any other reasons why
32 the executable file might be covered by the GNU General Public
33 License.
34
35 If you submit changes to SANE to the maintainers to be included in
36 a subsequent release, you agree by submitting the changes that
37 those changes may be distributed with this exception intact.
38
39 If you write modifications of your own for SANE, it is your choice
40 whether to permit this exception to apply to your modifications.
41 If you do not wish that, delete this exception notice.
42
43 **************************************************************************/
44
45 #undef BACKEND_NAME
46 #define BACKEND_NAME lexmark_low
47
48 #include "lexmark.h"
49
50 #include "lexmark_sensors.c"
51 #include "lexmark_models.c"
52
53 /* numbre of ranges for offset */
54 #define OFFSET_RANGES 5
55
56 typedef enum
57 {
58 black = 0,
59 white
60 }
61 region_type;
62
63 #define HomeTolerance 32
64
65
66 #define LOBYTE(x) ((uint8_t)((x) & 0xFF))
67 #define HIBYTE(x) ((uint8_t)((x) >> 8))
68
69 /* Static low function proto-types */
70 static SANE_Status low_usb_bulk_write (SANE_Int devnum,
71 SANE_Byte * cmd, size_t * size);
72 static SANE_Status low_usb_bulk_read (SANE_Int devnum,
73 SANE_Byte * buf, size_t * size);
74 static SANE_Status low_write_all_regs (SANE_Int devnum, SANE_Byte * regs);
75 static SANE_Bool low_is_home_line (Lexmark_Device * dev,
76 unsigned char *buffer);
77 static SANE_Status low_get_start_loc (SANE_Int resolution,
78 SANE_Int * vert_start,
79 SANE_Int * hor_start, SANE_Int offset,
80 Lexmark_Device * dev);
81 static void low_rewind (Lexmark_Device * dev, SANE_Byte * regs);
82 static SANE_Status low_start_mvmt (SANE_Int devnum);
83 static SANE_Status low_stop_mvmt (SANE_Int devnum);
84 static SANE_Status low_clr_c6 (SANE_Int devnum);
85 static SANE_Status low_simple_scan (Lexmark_Device * dev,
86 SANE_Byte * regs,
87 int xoffset,
88 int pixels,
89 int yoffset,
90 int lines, SANE_Byte ** data);
91 static void low_set_scan_area (SANE_Int res,
92 SANE_Int tlx,
93 SANE_Int tly,
94 SANE_Int brx,
95 SANE_Int bry,
96 SANE_Int offset,
97 SANE_Bool half_step,
98 SANE_Byte * regs, Lexmark_Device * dev);
99
100 /* Static Read Buffer Proto-types */
101 static SANE_Status read_buffer_init (Lexmark_Device * dev, int bytesperline);
102 static SANE_Status read_buffer_free (Read_Buffer * rb);
103 static size_t read_buffer_bytes_available (Read_Buffer * rb);
104 static SANE_Status read_buffer_add_byte (Read_Buffer * rb,
105 SANE_Byte * byte_pointer);
106 static SANE_Status read_buffer_add_byte_gray (Read_Buffer * rb,
107 SANE_Byte * byte_pointer);
108 static SANE_Status read_buffer_add_bit_lineart (Read_Buffer * rb,
109 SANE_Byte * byte_pointer,
110 SANE_Byte threshold);
111 static size_t read_buffer_get_bytes (Read_Buffer * rb, SANE_Byte * buffer,
112 size_t rqst_size);
113 static SANE_Bool read_buffer_is_empty (Read_Buffer * rb);
114
115
116 /*
117 * RTS88XX START
118 *
119 * these rts88xx functions will be spin off in a separate lib
120 * so that they can be reused.
121 */
122
123 /*
124 * registers helpers to avoid direct access
125 */
126 static SANE_Bool
rts88xx_is_color(SANE_Byte * regs)127 rts88xx_is_color (SANE_Byte * regs)
128 {
129 if ((regs[0x2f] & 0x11) == 0x11)
130 return SANE_TRUE;
131 return SANE_FALSE;
132 }
133
134 static void
rts88xx_set_gray_scan(SANE_Byte * regs)135 rts88xx_set_gray_scan (SANE_Byte * regs)
136 {
137 regs[0x2f] = (regs[0x2f] & 0x0f) | 0x20;
138 }
139
140 #if 0
141 static void
142 rts88xx_set_color_scan (SANE_Byte * regs)
143 {
144 regs[0x2f] = (regs[0x2f] & 0x0f) | 0x10;
145 }
146 #endif
147
148 static void
rts88xx_set_offset(SANE_Byte * regs,SANE_Byte red,SANE_Byte green,SANE_Byte blue)149 rts88xx_set_offset (SANE_Byte * regs, SANE_Byte red, SANE_Byte green,
150 SANE_Byte blue)
151 {
152 /* offset for odd pixels */
153 regs[0x02] = red;
154 regs[0x03] = green;
155 regs[0x04] = blue;
156
157 /* offset for even pixels */
158 regs[0x05] = red;
159 regs[0x06] = green;
160 regs[0x07] = blue;
161 }
162
163 static void
rts88xx_set_gain(SANE_Byte * regs,SANE_Byte red,SANE_Byte green,SANE_Byte blue)164 rts88xx_set_gain (SANE_Byte * regs, SANE_Byte red, SANE_Byte green,
165 SANE_Byte blue)
166 {
167 regs[0x08] = red;
168 regs[0x09] = green;
169 regs[0x0a] = blue;
170 }
171
172 /* set # of head moves per CIS read */
173 static int
rts88xx_set_scan_frequency(SANE_Byte * regs,int frequency)174 rts88xx_set_scan_frequency (SANE_Byte * regs, int frequency)
175 {
176 regs[0x64] = (regs[0x64] & 0xf0) | (frequency & 0x0f);
177 return 0;
178 }
179
180 /*
181 * read one register at given index
182 */
183 static SANE_Status
rts88xx_read_reg(SANE_Int devnum,SANE_Int index,SANE_Byte * reg)184 rts88xx_read_reg (SANE_Int devnum, SANE_Int index, SANE_Byte * reg)
185 {
186 SANE_Status status = SANE_STATUS_GOOD;
187 unsigned char cmd[] = { 0x80, 0x00, 0x00, 0x01 };
188 size_t size;
189
190 cmd[1] = index;
191
192 size = 4;
193 #ifdef FAKE_USB
194 status = SANE_STATUS_GOOD;
195 #else
196 status = sanei_usb_write_bulk (devnum, cmd, &size);
197 #endif
198 if (status != SANE_STATUS_GOOD)
199 {
200 DBG (5, "rts88xx_read_reg: bulk write failed\n");
201 return status;
202 }
203 size = 1;
204 #ifdef FAKE_USB
205 status = SANE_STATUS_GOOD;
206 #else
207 status = sanei_usb_read_bulk (devnum, reg, &size);
208 #endif
209 if (status != SANE_STATUS_GOOD)
210 {
211 DBG (5, "rts88xx_read_reg: bulk read failed\n");
212 return status;
213 }
214 DBG (15, "rts88xx_read_reg: reg[0x%02x]=0x%02x\n", index, *reg);
215 return status;
216 }
217
218 /*
219 * write one register at given index
220 */
221 static SANE_Status
rts88xx_write_reg(SANE_Int devnum,SANE_Int index,SANE_Byte * reg)222 rts88xx_write_reg (SANE_Int devnum, SANE_Int index, SANE_Byte * reg)
223 {
224 SANE_Status status = SANE_STATUS_GOOD;
225 unsigned char cmd[] = { 0x88, 0x00, 0x00, 0x01 };
226 size_t size;
227
228 cmd[1] = index;
229
230 size = 4;
231 #ifdef FAKE_USB
232 status = SANE_STATUS_GOOD;
233 #else
234 status = sanei_usb_write_bulk (devnum, cmd, &size);
235 #endif
236 if (status != SANE_STATUS_GOOD)
237 {
238 DBG (5, "rts88xx_write_reg: bulk write failed\n");
239 return status;
240 }
241 size = 1;
242 #ifdef FAKE_USB
243 status = SANE_STATUS_GOOD;
244 #else
245 status = sanei_usb_write_bulk (devnum, reg, &size);
246 #endif
247 if (status != SANE_STATUS_GOOD)
248 {
249 DBG (5, "rts88xx_write_reg: bulk write failed\n");
250 return status;
251 }
252 DBG (15, "rts88xx_write_reg: reg[0x%02x]=0x%02x\n", index, *reg);
253 return status;
254 }
255
256 /*
257 * write length consecutive registers, starting at index
258 * register 0xb3 is never wrote in bulk register write, so we split
259 * write if it belongs to the register set sent
260 */
261 static SANE_Status
rts88xx_write_regs(SANE_Int devnum,SANE_Int start,SANE_Byte * source,SANE_Int length)262 rts88xx_write_regs (SANE_Int devnum, SANE_Int start, SANE_Byte * source,
263 SANE_Int length)
264 {
265 size_t size = 0;
266
267 /* when writing several registers at a time, we avoid writing 0xb3
268 register */
269 if ((start + length > 0xb3) && (length > 1))
270 {
271 size = 0xb3 - start;
272 if (low_usb_bulk_write (devnum, source, &size) != SANE_STATUS_GOOD)
273 {
274 DBG (5, "rts88xx_write_regs : write registers part 1 failed ...\n");
275 return SANE_STATUS_IO_ERROR;
276 }
277
278 /* skip 0xB3 register */
279 size++;
280 start = 0xb4;
281 source = source + size;
282 }
283 size = length - size;
284 if (low_usb_bulk_write (devnum, source, &size) != SANE_STATUS_GOOD)
285 {
286 DBG (5, "rts88xx_write_regs : write registers part 2 failed ...\n");
287 return SANE_STATUS_IO_ERROR;
288 }
289
290 return SANE_STATUS_GOOD;
291
292 }
293
294 /*
295 * reads 'needed' bytes of scanned data into 'data'. Actual number of bytes get
296 * is returned in 'size'
297 */
298 static SANE_Status
rts88xx_read_data(SANE_Int devnum,size_t needed,SANE_Byte * data,size_t * size)299 rts88xx_read_data (SANE_Int devnum, size_t needed, SANE_Byte * data,
300 size_t * size)
301 {
302 SANE_Byte read_cmd[] = { 0x91, 0x00, 0x00, 0x00 };
303 size_t cmd_size;
304 SANE_Status status = SANE_STATUS_GOOD;
305
306 /* this block would deserve to be a function */
307 if (needed > MAX_XFER_SIZE)
308 *size = MAX_XFER_SIZE;
309 else
310 *size = needed;
311 read_cmd[3] = (*size) & 0xff;
312 read_cmd[2] = (*size >> 8) & 0xff;
313 read_cmd[1] = (*size >> 16) & 0xff;
314
315 /* send header for 'get scanned data' */
316 cmd_size = 4;
317 status = low_usb_bulk_write (devnum, read_cmd, &cmd_size);
318 if (status != SANE_STATUS_GOOD)
319 {
320 *size = 0;
321 DBG (5, "rts88xx_read_data : header sending failed ...\n");
322 return status;
323 }
324 /* get actual scanned data */
325 status = low_usb_bulk_read (devnum, data, size);
326 if (status != SANE_STATUS_GOOD)
327 {
328 *size = 0;
329 DBG (5, "rts88xx_read_data : data reading failed ...\n");
330 }
331 return status;
332 }
333
334 /* starts scan by sending color depth, stopping head, the starting it */
335 static SANE_Status
rts88xx_commit(SANE_Int devnum,SANE_Byte depth)336 rts88xx_commit (SANE_Int devnum, SANE_Byte depth)
337 {
338 SANE_Status status;
339 SANE_Byte reg;
340
341 DBG (2, "rts88xx_commit: start\n");
342
343 /* send color depth depth ??
344 * X1100 -> 0x0f
345 * X1100/B2 -> 0x0d
346 * X1200 -> 0x01 */
347 reg = depth;
348 rts88xx_write_reg (devnum, 0x2c, ®);
349
350 /* stop before starting */
351 low_stop_mvmt (devnum);
352
353 /* effective start */
354 status = low_start_mvmt (devnum);
355
356 DBG (2, "rts88xx_commit: end\n");
357
358 return status;
359 }
360
361 /*
362 * RTS88XX END
363 */
364
365
366
367 /*
368 * sets the scanner idle
369 */
370 static SANE_Status
lexmark_low_set_idle(SANE_Int devnum)371 lexmark_low_set_idle (SANE_Int devnum)
372 {
373 SANE_Byte regs[14] =
374 { 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x60
376 };
377 if (rts88xx_write_regs (devnum, 16, regs, 14) != SANE_STATUS_GOOD)
378 {
379 DBG (5, "lexmark_low_set_idle : register write failed ...\n");
380 return SANE_STATUS_IO_ERROR;
381 }
382 return SANE_STATUS_GOOD;
383 }
384
385
386 /* wake up scanner */
387 #if 0
388 static SANE_Status
389 lexmark_low_wake_up (Lexmark_Device * dev)
390 {
391 SANE_Byte regs[5] = { 0x12, 0x14, 0x16, 0x18, 0x1a };
392 SANE_Byte values[5] = { 0x0f, 0x00, 0x07, 0x00, 0x00 };
393 int i;
394
395 /* send the wake-up sequence, one reg at at time */
396 for (i = 0; i < 10; i++)
397 {
398 if (rts88xx_write_reg (dev->devnum, regs[i], values + i) !=
399 SANE_STATUS_GOOD)
400 {
401 DBG (5,
402 "lexmark_low_wake_up : register write pass %d failed ...\n",
403 i);
404 return SANE_STATUS_IO_ERROR;
405 }
406 }
407 return SANE_STATUS_GOOD;
408 }
409 #endif
410
411
412 /**
413 *
414 */
415 #ifdef DEEP_DEBUG
416 static void
write_pnm_file(char * title,int pixels,int lines,int color,unsigned char * data)417 write_pnm_file (char *title, int pixels, int lines, int color,
418 unsigned char *data)
419 {
420 FILE *fdbg;
421 int x, y;
422
423 fdbg = fopen (title, "wb");
424 if (fdbg == NULL)
425 return;
426
427 if (color)
428 {
429 fprintf (fdbg, "P6\n%d %d\n255\n", pixels, lines);
430 for (y = 0; y < lines; y++)
431 {
432 for (x = 0; x < pixels; x += 2)
433 {
434 fputc (data[y * pixels * 3 + x + 1], fdbg);
435 fputc (data[y * pixels * 3 + x + 1 + pixels], fdbg);
436 fputc (data[y * pixels * 3 + x + 1 + pixels * 2], fdbg);
437 fputc (data[y * pixels * 3 + x], fdbg);
438 fputc (data[y * pixels * 3 + x + pixels], fdbg);
439 fputc (data[y * pixels * 3 + x + pixels * 2], fdbg);
440 }
441 }
442 }
443 else
444 {
445 fprintf (fdbg, "P5\n%d %d\n255\n", pixels, lines);
446 fwrite (data, pixels, lines, fdbg);
447 }
448 fclose (fdbg);
449 }
450 #endif
451
452 /*
453 * mid level hardware functions
454 */
455 /*
456 * model init
457 */
458 SANE_Status
sanei_lexmark_low_init(Lexmark_Device * dev)459 sanei_lexmark_low_init (Lexmark_Device * dev)
460 {
461 int i;
462 SANE_Status status;
463
464 DBG_INIT ();
465
466 status = SANE_STATUS_UNSUPPORTED;
467 DBG (2, "low_init: start\n");
468
469 /* clear all registers first */
470 for (i = 0; i < 255; i++)
471 {
472 dev->shadow_regs[i] = 0;
473 }
474
475 /* set up per model constant values */
476 dev->shadow_regs[0xf3] = 0xf8;
477 dev->shadow_regs[0xf4] = 0x7f;
478
479 switch (dev->model.sensor_type)
480 {
481 case X74_SENSOR:
482 dev->shadow_regs[0x00] = 0x04;
483 dev->shadow_regs[0x01] = 0x43;
484 dev->shadow_regs[0x0b] = 0x70;
485 dev->shadow_regs[0x12] = 0x0f;
486 dev->shadow_regs[0x16] = 0x07;
487 dev->shadow_regs[0x1d] = 0x20;
488 dev->shadow_regs[0x28] = 0xe0;
489 dev->shadow_regs[0x29] = 0xe3;
490 dev->shadow_regs[0x2a] = 0xeb;
491 dev->shadow_regs[0x2b] = 0x0d;
492 dev->shadow_regs[0x2e] = 0x40;
493 dev->shadow_regs[0x2e] = 0x86;
494 dev->shadow_regs[0x2f] = 0x01;
495 dev->shadow_regs[0x30] = 0x48;
496 dev->shadow_regs[0x31] = 0x06;
497 dev->shadow_regs[0x33] = 0x01;
498 dev->shadow_regs[0x34] = 0x50;
499 dev->shadow_regs[0x35] = 0x01;
500 dev->shadow_regs[0x36] = 0x50;
501 dev->shadow_regs[0x37] = 0x01;
502 dev->shadow_regs[0x38] = 0x50;
503 dev->shadow_regs[0x3a] = 0x20;
504 dev->shadow_regs[0x3c] = 0x88;
505 dev->shadow_regs[0x3d] = 0x08;
506 dev->shadow_regs[0x65] = 0x80;
507 dev->shadow_regs[0x66] = 0x64;
508 dev->shadow_regs[0x6c] = 0xc8;
509 dev->shadow_regs[0x72] = 0x1a;
510 dev->shadow_regs[0x74] = 0x23;
511 dev->shadow_regs[0x75] = 0x03;
512 dev->shadow_regs[0x79] = 0x40;
513 dev->shadow_regs[0x7A] = 0x01;
514 dev->shadow_regs[0x8d] = 0x01;
515 dev->shadow_regs[0x8e] = 0x60;
516 dev->shadow_regs[0x8f] = 0x80;
517 dev->shadow_regs[0x93] = 0x02;
518 dev->shadow_regs[0x94] = 0x0e;
519 dev->shadow_regs[0xa3] = 0xcc;
520 dev->shadow_regs[0xa4] = 0x27;
521 dev->shadow_regs[0xa5] = 0x24;
522 dev->shadow_regs[0xc2] = 0x80;
523 dev->shadow_regs[0xc3] = 0x01;
524 dev->shadow_regs[0xc4] = 0x20;
525 dev->shadow_regs[0xc5] = 0x0a;
526 dev->shadow_regs[0xc8] = 0x04;
527 dev->shadow_regs[0xc9] = 0x39;
528 dev->shadow_regs[0xca] = 0x0a;
529 dev->shadow_regs[0xe2] = 0x70;
530 dev->shadow_regs[0xe3] = 0x17;
531 dev->shadow_regs[0xf3] = 0xe0;
532 dev->shadow_regs[0xf4] = 0xff;
533 dev->shadow_regs[0xf5] = 0x01;
534 status = SANE_STATUS_GOOD;
535 break;
536 case X1100_B2_SENSOR:
537 dev->shadow_regs[0x01] = 0x43;
538 dev->shadow_regs[0x0b] = 0x70;
539 dev->shadow_regs[0x11] = 0x01;
540 dev->shadow_regs[0x12] = 0x0f;
541 dev->shadow_regs[0x13] = 0x01;
542 dev->shadow_regs[0x15] = 0x01;
543 dev->shadow_regs[0x16] = 0x0f;
544 dev->shadow_regs[0x1d] = 0x20;
545 dev->shadow_regs[0x28] = 0xeb;
546 dev->shadow_regs[0x29] = 0xee;
547 dev->shadow_regs[0x2a] = 0xf7;
548 dev->shadow_regs[0x2b] = 0x01;
549 dev->shadow_regs[0x2e] = 0x86;
550 dev->shadow_regs[0x30] = 0x48;
551 dev->shadow_regs[0x33] = 0x01;
552 dev->shadow_regs[0x3a] = 0x20;
553 dev->shadow_regs[0x3b] = 0x37;
554 dev->shadow_regs[0x3c] = 0x88;
555 dev->shadow_regs[0x3d] = 0x08;
556 dev->shadow_regs[0x40] = 0x80;
557 dev->shadow_regs[0x72] = 0x05;
558 dev->shadow_regs[0x74] = 0x0e;
559 dev->shadow_regs[0x8b] = 0xff;
560 dev->shadow_regs[0x8c] = 0x02;
561 dev->shadow_regs[0x8d] = 0x01;
562 dev->shadow_regs[0x8e] = 0x60;
563 dev->shadow_regs[0x8f] = 0x80;
564 dev->shadow_regs[0x94] = 0x0e;
565 dev->shadow_regs[0xa3] = 0xcc;
566 dev->shadow_regs[0xa4] = 0x27;
567 dev->shadow_regs[0xa5] = 0x24;
568 dev->shadow_regs[0xb0] = 0xb2;
569 dev->shadow_regs[0xb2] = 0x04;
570 dev->shadow_regs[0xc2] = 0x80;
571 dev->shadow_regs[0xc4] = 0x20;
572 dev->shadow_regs[0xc8] = 0x04;
573 dev->shadow_regs[0xc9] = 0x3b;
574 dev->shadow_regs[0xed] = 0xc2;
575 dev->shadow_regs[0xee] = 0x02;
576 status = SANE_STATUS_GOOD;
577 break;
578 case X1100_2C_SENSOR:
579 dev->shadow_regs[0x00] = 0x00;
580 dev->shadow_regs[0x01] = 0x43;
581 dev->shadow_regs[0x0b] = 0x70;
582 dev->shadow_regs[0x0c] = 0x28;
583 dev->shadow_regs[0x0d] = 0xa4;
584 dev->shadow_regs[0x11] = 0x01;
585 dev->shadow_regs[0x12] = 0x0f;
586 dev->shadow_regs[0x13] = 0x01;
587 dev->shadow_regs[0x15] = 0x01;
588 dev->shadow_regs[0x16] = 0x0f;
589 dev->shadow_regs[0x17] = 0x00;
590 dev->shadow_regs[0x1d] = 0x20;
591 dev->shadow_regs[0x28] = 0xf5;
592 dev->shadow_regs[0x29] = 0xf7;
593 dev->shadow_regs[0x2a] = 0xf5;
594 dev->shadow_regs[0x2b] = 0x17;
595 dev->shadow_regs[0x2d] = 0x41;
596 dev->shadow_regs[0x2e] = 0x86;
597 dev->shadow_regs[0x2f] = 0x11;
598 dev->shadow_regs[0x30] = 0x48;
599 dev->shadow_regs[0x31] = 0x01;
600 dev->shadow_regs[0x33] = 0x01;
601 dev->shadow_regs[0x34] = 0x50;
602 dev->shadow_regs[0x35] = 0x01;
603 dev->shadow_regs[0x36] = 0x50;
604 dev->shadow_regs[0x37] = 0x01;
605 dev->shadow_regs[0x38] = 0x50;
606 dev->shadow_regs[0x3a] = 0x20;
607 dev->shadow_regs[0x3b] = 0x37;
608 dev->shadow_regs[0x3c] = 0x88;
609 dev->shadow_regs[0x3d] = 0x08;
610 dev->shadow_regs[0x40] = 0x80;
611 dev->shadow_regs[0x47] = 0x01;
612 dev->shadow_regs[0x48] = 0x1a;
613 dev->shadow_regs[0x49] = 0x5b;
614 dev->shadow_regs[0x4a] = 0x1b;
615 dev->shadow_regs[0x4b] = 0x5b;
616 dev->shadow_regs[0x4c] = 0x05;
617 dev->shadow_regs[0x4d] = 0x3f;
618 dev->shadow_regs[0x60] = 0x2f;
619 dev->shadow_regs[0x61] = 0x36;
620 dev->shadow_regs[0x62] = 0x30;
621 dev->shadow_regs[0x63] = 0x36;
622 dev->shadow_regs[0x65] = 0x80;
623 dev->shadow_regs[0x66] = 0x64;
624 dev->shadow_regs[0x6c] = 0xc8;
625 dev->shadow_regs[0x6d] = 0x00;
626 dev->shadow_regs[0x72] = 0x35;
627 dev->shadow_regs[0x74] = 0x4e;
628 dev->shadow_regs[0x75] = 0x03;
629 dev->shadow_regs[0x79] = 0x40;
630 dev->shadow_regs[0x7a] = 0x01;
631 dev->shadow_regs[0x85] = 0x02;
632 dev->shadow_regs[0x86] = 0x33;
633 dev->shadow_regs[0x87] = 0x0f;
634 dev->shadow_regs[0x88] = 0x24;
635 dev->shadow_regs[0x8b] = 0xff;
636 dev->shadow_regs[0x8c] = 0x02;
637 dev->shadow_regs[0x8d] = 0x01;
638 dev->shadow_regs[0x8e] = 0x60;
639 dev->shadow_regs[0x8f] = 0x80;
640 dev->shadow_regs[0x91] = 0x19;
641 dev->shadow_regs[0x92] = 0x20;
642 dev->shadow_regs[0x93] = 0x02;
643 dev->shadow_regs[0x94] = 0x0e;
644 dev->shadow_regs[0xa3] = 0x0d;
645 dev->shadow_regs[0xa4] = 0x5e;
646 dev->shadow_regs[0xa5] = 0x23;
647 dev->shadow_regs[0xb0] = 0x2c;
648 dev->shadow_regs[0xb1] = 0x07;
649 dev->shadow_regs[0xb2] = 0x04;
650 dev->shadow_regs[0xc2] = 0x80;
651 dev->shadow_regs[0xc3] = 0x01;
652 dev->shadow_regs[0xc4] = 0x20;
653 dev->shadow_regs[0xc5] = 0x0a;
654 dev->shadow_regs[0xc8] = 0x04;
655 dev->shadow_regs[0xc9] = 0x3b;
656 dev->shadow_regs[0xca] = 0x0a;
657 dev->shadow_regs[0xe2] = 0xf8;
658 dev->shadow_regs[0xe3] = 0x2a;
659 status = SANE_STATUS_GOOD;
660 break;
661 case X1200_USB2_SENSOR:
662 dev->shadow_regs[0x01] = 0x43;
663 dev->shadow_regs[0x11] = 0x01;
664 dev->shadow_regs[0x12] = 0x0f;
665 dev->shadow_regs[0x13] = 0x01;
666 dev->shadow_regs[0x15] = 0x01;
667 dev->shadow_regs[0x16] = 0x0f;
668 dev->shadow_regs[0x17] = 0x00;
669 dev->shadow_regs[0x1d] = 0x20;
670 dev->shadow_regs[0x28] = 0xf5;
671 dev->shadow_regs[0x29] = 0xf7;
672 dev->shadow_regs[0x2a] = 0xf5;
673 dev->shadow_regs[0x2b] = 0x17;
674 dev->shadow_regs[0x2d] = 0x41;
675 dev->shadow_regs[0x2e] = 0x86;
676 dev->shadow_regs[0x30] = 0x48;
677 dev->shadow_regs[0x31] = 0x01;
678 dev->shadow_regs[0x33] = 0x01;
679 dev->shadow_regs[0x34] = 0x50;
680 dev->shadow_regs[0x35] = 0x01;
681 dev->shadow_regs[0x36] = 0x50;
682 dev->shadow_regs[0x37] = 0x01;
683 dev->shadow_regs[0x38] = 0x50;
684 dev->shadow_regs[0x3c] = 0x88;
685 dev->shadow_regs[0x3d] = 0x08;
686 dev->shadow_regs[0x66] = 0x64;
687 dev->shadow_regs[0x67] = 0x00;
688 dev->shadow_regs[0x6c] = 0xc8;
689 dev->shadow_regs[0x6d] = 0x00;
690 dev->shadow_regs[0x72] = 0x35;
691 dev->shadow_regs[0x74] = 0x4e;
692 dev->shadow_regs[0x75] = 0x03;
693 dev->shadow_regs[0x7a] = 0x01;
694 dev->shadow_regs[0x93] = 0x0a;
695 dev->shadow_regs[0x94] = 0x0e;
696
697 dev->shadow_regs[0xc3] = 0x01;
698 dev->shadow_regs[0xc4] = 0x20;
699 dev->shadow_regs[0xc5] = 0x0a;
700 dev->shadow_regs[0xc8] = 0x04;
701 dev->shadow_regs[0xc9] = 0x3b;
702 dev->shadow_regs[0xca] = 0x0a;
703 dev->shadow_regs[0xe2] = 0xf8;
704 dev->shadow_regs[0xe3] = 0x2a;
705 status = SANE_STATUS_GOOD;
706 break;
707 case A920_SENSOR:
708 dev->shadow_regs[0x01] = 0x43;
709 dev->shadow_regs[0x0b] = 0x70;
710 dev->shadow_regs[0x0c] = 0x28;
711 dev->shadow_regs[0x0d] = 0xa4;
712 dev->shadow_regs[0x11] = 0x01;
713 dev->shadow_regs[0x12] = 0x0f;
714 dev->shadow_regs[0x13] = 0x01;
715 dev->shadow_regs[0x15] = 0x01;
716 dev->shadow_regs[0x16] = 0x07;
717 dev->shadow_regs[0x1d] = 0x20;
718 dev->shadow_regs[0x28] = 0xf5;
719 dev->shadow_regs[0x29] = 0xf7;
720 dev->shadow_regs[0x2a] = 0xf5;
721 dev->shadow_regs[0x2b] = 0x17;
722 dev->shadow_regs[0x2e] = 0x86;
723 dev->shadow_regs[0x30] = 0x48;
724 dev->shadow_regs[0x31] = 0x01;
725 dev->shadow_regs[0x33] = 0x01;
726 dev->shadow_regs[0x3a] = 0x20;
727 dev->shadow_regs[0x3b] = 0x37;
728 dev->shadow_regs[0x3c] = 0x88;
729 dev->shadow_regs[0x3d] = 0x08;
730 dev->shadow_regs[0x47] = 0x21;
731 dev->shadow_regs[0x48] = 0x1a;
732 dev->shadow_regs[0x49] = 0x5b;
733 dev->shadow_regs[0x4a] = 0x1b;
734 dev->shadow_regs[0x4b] = 0x5b;
735 dev->shadow_regs[0x4c] = 0x05;
736 dev->shadow_regs[0x4d] = 0x3f;
737 dev->shadow_regs[0x65] = 0x80;
738 dev->shadow_regs[0x86] = 0x14;
739 dev->shadow_regs[0x87] = 0x06;
740 dev->shadow_regs[0x89] = 0xf5;
741 dev->shadow_regs[0x8d] = 0x01;
742 dev->shadow_regs[0x8e] = 0x60;
743 dev->shadow_regs[0x8f] = 0x80;
744 dev->shadow_regs[0x94] = 0x0e;
745 dev->shadow_regs[0xa3] = 0x0d;
746 dev->shadow_regs[0xa4] = 0x5e;
747 dev->shadow_regs[0xa5] = 0x23;
748 dev->shadow_regs[0xb0] = 0x2c;
749 dev->shadow_regs[0xb1] = 0x0f;
750 dev->shadow_regs[0xc2] = 0x80;
751 dev->shadow_regs[0xc4] = 0x20;
752 dev->shadow_regs[0xc8] = 0x04;
753 status = SANE_STATUS_GOOD;
754 break;
755 case X1200_SENSOR:
756 dev->shadow_regs[0x01] = 0x43;
757 dev->shadow_regs[0x0b] = 0x70;
758 dev->shadow_regs[0x0c] = 0x28;
759 dev->shadow_regs[0x0d] = 0xa4;
760 dev->shadow_regs[0x11] = 0x01;
761 dev->shadow_regs[0x12] = 0x0f;
762 dev->shadow_regs[0x13] = 0x01;
763 dev->shadow_regs[0x15] = 0x01;
764 dev->shadow_regs[0x16] = 0x0f;
765 dev->shadow_regs[0x1d] = 0x20;
766 dev->shadow_regs[0x28] = 0xe9;
767 dev->shadow_regs[0x29] = 0xeb;
768 dev->shadow_regs[0x2a] = 0xe9;
769 dev->shadow_regs[0x2b] = 0x0b;
770 dev->shadow_regs[0x2d] = 0x01;
771 dev->shadow_regs[0x2e] = 0x86;
772 dev->shadow_regs[0x2f] = 0x11;
773 dev->shadow_regs[0x30] = 0x48;
774 dev->shadow_regs[0x33] = 0x01;
775 dev->shadow_regs[0x34] = 0x50;
776 dev->shadow_regs[0x35] = 0x01;
777 dev->shadow_regs[0x36] = 0x50;
778 dev->shadow_regs[0x37] = 0x01;
779 dev->shadow_regs[0x38] = 0x50;
780 dev->shadow_regs[0x3a] = 0x20;
781 dev->shadow_regs[0x3b] = 0x37;
782 dev->shadow_regs[0x3c] = 0x88;
783 dev->shadow_regs[0x3d] = 0x08;
784 dev->shadow_regs[0x40] = 0x80;
785 dev->shadow_regs[0x47] = 0x01;
786 dev->shadow_regs[0x48] = 0x1a;
787 dev->shadow_regs[0x49] = 0x5b;
788 dev->shadow_regs[0x4a] = 0x1b;
789 dev->shadow_regs[0x4b] = 0x5b;
790 dev->shadow_regs[0x4c] = 0x05;
791 dev->shadow_regs[0x4d] = 0x3f;
792 dev->shadow_regs[0x60] = 0x12;
793 dev->shadow_regs[0x62] = 0x81;
794 dev->shadow_regs[0x63] = 0x03;
795 dev->shadow_regs[0x65] = 0x80;
796 dev->shadow_regs[0x66] = 0x64;
797 dev->shadow_regs[0x6c] = 0xc8;
798 dev->shadow_regs[0x72] = 0x1e;
799 dev->shadow_regs[0x74] = 0x3c;
800 dev->shadow_regs[0x75] = 0x03;
801 dev->shadow_regs[0x79] = 0x40;
802 dev->shadow_regs[0x7a] = 0x01;
803 dev->shadow_regs[0x85] = 0x20;
804 dev->shadow_regs[0x86] = 0x1e;
805 dev->shadow_regs[0x87] = 0x39;
806 dev->shadow_regs[0x8b] = 0xff;
807 dev->shadow_regs[0x8c] = 0x02;
808 dev->shadow_regs[0x8d] = 0x01;
809 dev->shadow_regs[0x8e] = 0x60;
810 dev->shadow_regs[0x8f] = 0x80;
811 dev->shadow_regs[0x92] = 0x92;
812 dev->shadow_regs[0x93] = 0x02;
813 dev->shadow_regs[0x94] = 0x0e;
814 dev->shadow_regs[0xa3] = 0x0d;
815 dev->shadow_regs[0xa4] = 0x5e;
816 dev->shadow_regs[0xa5] = 0x23;
817 dev->shadow_regs[0xb0] = 0x2c;
818 dev->shadow_regs[0xb1] = 0x07;
819 dev->shadow_regs[0xb2] = 0x04;
820 dev->shadow_regs[0xc2] = 0x80;
821 dev->shadow_regs[0xc3] = 0x01;
822 dev->shadow_regs[0xc4] = 0x20;
823 dev->shadow_regs[0xc5] = 0x0a;
824 dev->shadow_regs[0xc8] = 0x04;
825 dev->shadow_regs[0xc9] = 0x3b;
826 dev->shadow_regs[0xca] = 0x0a;
827 dev->shadow_regs[0xe2] = 0xf8;
828 dev->shadow_regs[0xe3] = 0x2a;
829 dev->shadow_regs[0xf3] = 0xff;
830 dev->shadow_regs[0xf4] = 0x0f;
831 break;
832 }
833 DBG (5, "sanei_lexmark_low_init: init done for model %s/%s\n",
834 dev->model.model, dev->model.name);
835 DBG (2, "low_init: done\n");
836 return status;
837 }
838
839 void
sanei_lexmark_low_destroy(Lexmark_Device * dev)840 sanei_lexmark_low_destroy (Lexmark_Device * dev)
841 {
842 /* free the read buffer */
843 if (dev->read_buffer != NULL)
844 read_buffer_free (dev->read_buffer);
845 }
846
847
848 SANE_Status
low_usb_bulk_write(SANE_Int devnum,SANE_Byte * cmd,size_t * size)849 low_usb_bulk_write (SANE_Int devnum, SANE_Byte * cmd, size_t * size)
850 {
851 SANE_Status status;
852 size_t cmd_size;
853
854 cmd_size = *size;
855 #ifdef FAKE_USB
856 status = SANE_STATUS_GOOD;
857 #else
858 status = sanei_usb_write_bulk (devnum, cmd, size);
859 #endif
860 if (status != SANE_STATUS_GOOD)
861 {
862 DBG (5,
863 "low_usb_bulk_write: returned %s (size = %lu, expected %lu)\n",
864 sane_strstatus (status), (u_long) * size, (u_long) cmd_size);
865 /* F.O. should reset the pipe here... */
866 }
867 return status;
868 }
869
870 SANE_Status
low_usb_bulk_read(SANE_Int devnum,SANE_Byte * buf,size_t * size)871 low_usb_bulk_read (SANE_Int devnum, SANE_Byte * buf, size_t * size)
872 {
873 SANE_Status status;
874 size_t exp_size;
875
876 exp_size = *size;
877 #ifdef FAKE_USB
878 status = SANE_STATUS_GOOD;
879 #else
880 status = sanei_usb_read_bulk (devnum, buf, size);
881 #endif
882 if (status != SANE_STATUS_GOOD)
883 {
884 DBG (5,
885 "low_usb_bulk_read: returned %s (size = %lu, expected %lu)\n",
886 sane_strstatus (status), (u_long) * size, (u_long) exp_size);
887 /* F.O. should reset the pipe here... */
888 }
889 DBG (7, "low_usb_bulk_read: returned size = %lu (required %lu)\n",
890 (u_long) * size, (u_long) exp_size);
891 return status;
892 }
893
894
895 SANE_Status
low_start_mvmt(SANE_Int devnum)896 low_start_mvmt (SANE_Int devnum)
897 {
898 SANE_Status status;
899 SANE_Byte reg;
900
901 reg = 0x68;
902 rts88xx_write_reg (devnum, 0xb3, ®);
903 status = rts88xx_write_reg (devnum, 0xb3, ®);
904 return status;
905 }
906
907 SANE_Status
low_stop_mvmt(SANE_Int devnum)908 low_stop_mvmt (SANE_Int devnum)
909 {
910 SANE_Status status;
911 SANE_Byte reg;
912
913 /* Stop scanner - clear reg 0xb3: */
914 reg = 0x02;
915 rts88xx_write_reg (devnum, 0xb3, ®);
916 rts88xx_write_reg (devnum, 0xb3, ®);
917 reg = 0x00;
918 rts88xx_write_reg (devnum, 0xb3, ®);
919 status = rts88xx_write_reg (devnum, 0xb3, ®);
920 return status;
921 }
922
923 SANE_Status
low_clr_c6(SANE_Int devnum)924 low_clr_c6 (SANE_Int devnum)
925 {
926 SANE_Status status;
927 SANE_Byte reg;
928
929 /* Clear register 0xC6 */
930 /* cmd_size = 0x05;
931 return low_usb_bulk_write (devnum, clearC6_command_block, &cmd_size); */
932
933 reg = 0x00;
934 status = rts88xx_write_reg (devnum, 0xc6, ®);
935 return status;
936 }
937
938 /* stops current scan */
939 static SANE_Status
low_cancel(SANE_Int devnum)940 low_cancel (SANE_Int devnum)
941 {
942 SANE_Status status;
943
944 DBG (2, "low_cancel: start\n");
945 status = low_stop_mvmt (devnum);
946 if (status != SANE_STATUS_GOOD)
947 return status;
948 status = low_clr_c6 (devnum);
949 if (status != SANE_STATUS_GOOD)
950 return status;
951 DBG (2, "low_cancel: end.\n");
952 return status;
953 }
954
955 static SANE_Status
low_start_scan(SANE_Int devnum,SANE_Byte * regs)956 low_start_scan (SANE_Int devnum, SANE_Byte * regs)
957 {
958 SANE_Status status;
959
960 DBG (2, "low_start_scan: start\n");
961
962 /* writes registers to scanner */
963 regs[0x32] = 0x00;
964 status = low_write_all_regs (devnum, regs);
965 if (status != SANE_STATUS_GOOD)
966 return status;
967 regs[0x32] = 0x40;
968 status = low_write_all_regs (devnum, regs);
969 if (status != SANE_STATUS_GOOD)
970 return status;
971
972 /* Stop scanner - clear reg 0xb3: */
973 /* status = low_stop_mvmt (devnum);
974 if (status != SANE_STATUS_GOOD)
975 return status; */
976
977 /* then start */
978 status = rts88xx_commit (devnum, regs[0x2c]);
979 DBG (2, "low_start_scan: end.\n");
980 return status;
981 }
982
983 /* wait for scan data being available */
984 static SANE_Status
low_poll_data(SANE_Int devnum)985 low_poll_data (SANE_Int devnum)
986 {
987 SANE_Status status;
988 int loops = 0;
989 size_t size;
990 static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 };
991 SANE_Byte result[3];
992 SANE_Word count;
993
994 /* Poll the available byte count until not 0 */
995 while (loops < 1000)
996 {
997 /* 10 ms sleep */
998 usleep (10000);
999
1000 /* as stated in sanei_lexmark_low_search_home_bwd, we read
1001 * available data count twice */
1002 size = 4;
1003 status = low_usb_bulk_write (devnum, command4_block, &size);
1004 if (status != SANE_STATUS_GOOD)
1005 return status;
1006 size = 0x3;
1007 status = low_usb_bulk_read (devnum, result, &size);
1008 if (status != SANE_STATUS_GOOD)
1009 return status;
1010 size = 4;
1011 /* read available data size again */
1012 status = low_usb_bulk_write (devnum, command4_block, &size);
1013 if (status != SANE_STATUS_GOOD)
1014 return status;
1015 size = 0x3;
1016 status = low_usb_bulk_read (devnum, result, &size);
1017 if (status != SANE_STATUS_GOOD)
1018 return status;
1019 count = result[0] + (result[1] << 8) + (result[2] << 16);
1020 if (count != 0)
1021 {
1022 DBG (15, "low_poll_data: %d bytes available\n", count);
1023 return SANE_STATUS_GOOD;
1024 }
1025 loops++;
1026 }
1027 return SANE_STATUS_IO_ERROR;
1028 }
1029
1030 /**
1031 * do a simple scan with the given registers. data buffer is allocated within
1032 * the function
1033 */
1034 static SANE_Status
low_simple_scan(Lexmark_Device * dev,SANE_Byte * regs,int xoffset,int pixels,int yoffset,int lines,SANE_Byte ** data)1035 low_simple_scan (Lexmark_Device * dev, SANE_Byte * regs, int xoffset,
1036 int pixels, int yoffset, int lines, SANE_Byte ** data)
1037 {
1038 SANE_Status status = SANE_STATUS_GOOD;
1039 static SANE_Byte reg;
1040 size_t size, read, needed;
1041 int i, bpl, yend;
1042
1043 DBG (2, "low_simple_scan: start\n");
1044 DBG (15, "low_simple_scan: x=%d, pixels=%d (ex=%d), y=%d, lines=%d\n",
1045 xoffset, pixels, xoffset + pixels * regs[0x7a], yoffset, lines);
1046
1047 /* set up registers */
1048 regs[0x60] = LOBYTE (yoffset);
1049 regs[0x61] = HIBYTE (yoffset);
1050 yend = yoffset + lines;
1051 if ((dev->model.motor_type == A920_MOTOR
1052 || dev->model.motor_type == X74_MOTOR) && rts88xx_is_color (regs)
1053 && dev->val[OPT_RESOLUTION].w == 600)
1054 yend *= 2;
1055 regs[0x62] = LOBYTE (yend);
1056 regs[0x63] = HIBYTE (yend);
1057
1058 regs[0x66] = LOBYTE (xoffset);
1059 regs[0x67] = HIBYTE (xoffset);
1060
1061 regs[0x6c] = LOBYTE (xoffset + pixels * regs[0x7a]);
1062 regs[0x6d] = HIBYTE (xoffset + pixels * regs[0x7a]);
1063
1064 /* allocate memory */
1065 if (rts88xx_is_color (regs))
1066 bpl = 3 * pixels;
1067 else
1068 bpl = pixels;
1069 *data = (SANE_Byte *) malloc (bpl * lines);
1070 if (*data == NULL)
1071 {
1072 DBG (2,
1073 "low_simple_scan: failed to allocate %d bytes !\n", bpl * lines);
1074 return SANE_STATUS_NO_MEM;
1075 }
1076
1077 /* start scan */
1078 status = low_cancel (dev->devnum);
1079 if (status != SANE_STATUS_GOOD)
1080 return status;
1081
1082
1083 status = low_start_scan (dev->devnum, regs);
1084 if (status != SANE_STATUS_GOOD)
1085 return status;
1086
1087 /* wait for data */
1088 status = low_poll_data (dev->devnum);
1089 if (status != SANE_STATUS_GOOD)
1090 {
1091 DBG (1, "low_simple_scan: time-out while waiting for data.\n");
1092 return status;
1093 }
1094
1095 /* data reading loop */
1096 needed = bpl * lines;
1097 DBG (1, "low_simple_scan: bpl=%d, lines=%d, needed=%lu.\n", bpl, lines,
1098 (u_long) needed);
1099 read = 0;
1100 do
1101 {
1102 /* this block would deserve to be a function */
1103 status =
1104 rts88xx_read_data (dev->devnum, needed - read, (*data) + read, &size);
1105 if (status != SANE_STATUS_GOOD)
1106 return status;
1107 read += size;
1108 }
1109 while (read < needed);
1110
1111 /* if needed, wait for motor to stop */
1112 if (regs[0xc3] & 0x80)
1113 {
1114 i = 0;
1115 do
1116 {
1117 if (rts88xx_read_reg (dev->devnum, 0xb3, ®) != SANE_STATUS_GOOD)
1118 {
1119 DBG (5, "low_simple_scan: register read failed ...\n");
1120 return SANE_STATUS_IO_ERROR;
1121 }
1122 usleep (100000);
1123 i++;
1124 }
1125 while ((reg & 0x08) && (i < 100));
1126 if (reg & 0x08)
1127 {
1128 DBG (5,
1129 "low_simple_scan : timeout waiting for motor to stop ...\n");
1130 return SANE_STATUS_IO_ERROR;
1131 }
1132 }
1133
1134 /* stop scan */
1135 status = low_cancel (dev->devnum);
1136 if (status != SANE_STATUS_GOOD)
1137 {
1138 DBG (1, "low_simple_scan: cancel failed.\n");
1139 return status;
1140 }
1141
1142 DBG (2, "low_simple_scan: end.\n");
1143 return status;
1144 }
1145
1146 /*
1147 * open USB device ,read initial registers values and probe sensor
1148 */
1149 SANE_Status
sanei_lexmark_low_open_device(Lexmark_Device * dev)1150 sanei_lexmark_low_open_device (Lexmark_Device * dev)
1151 {
1152 /* This function calls the Sane Interface to open this usb device.
1153 It also needlessly does what the Windows driver does and reads
1154 the entire register set - this may be removed. */
1155
1156 SANE_Status result;
1157 static SANE_Byte command_block[] = { 0x80, 0, 0x00, 0xFF };
1158 size_t size;
1159 SANE_Byte variant = 0;
1160 SANE_Byte shadow_regs[255];
1161 int sx, ex;
1162 int sy, ey;
1163 int i;
1164 char msg[2048];
1165
1166
1167 #ifdef FAKE_USB
1168 result = SANE_STATUS_GOOD;
1169 shadow_regs[0x00] = 0x91;
1170 shadow_regs[0xb0] = 0x2c;
1171 shadow_regs[0x10] = 0x97;
1172 shadow_regs[0x10] = 0x87;
1173 shadow_regs[0xf3] = 0xf8;
1174 shadow_regs[0xf4] = 0x7f;
1175 #else
1176 result = sanei_usb_open (dev->sane.name, &(dev->devnum));
1177 #endif
1178 DBG (2, "sanei_lexmark_low_open_device: devnum=%d\n", dev->devnum);
1179
1180 size = 4;
1181 low_usb_bulk_write (dev->devnum, command_block, &size);
1182 size = 0xFF;
1183 memset (shadow_regs, 0, sizeof (shadow_regs));
1184 low_usb_bulk_read (dev->devnum, shadow_regs, &size);
1185
1186 if (DBG_LEVEL > 2)
1187 {
1188 DBG (2, "sanei_lexmark_low_open_device: initial registers values\n");
1189 for (i = 0; i < 255; i++)
1190 {
1191 sprintf (msg + i * 5, "0x%02x ", shadow_regs[i]);
1192 }
1193 DBG (3, "%s\n", msg);
1194 }
1195
1196 /* it seems that at first read after reset, registers hold information
1197 * about the scanner. Register 0x00 is overwritten with 0, so only first read
1198 * after USB plug-in gives this value */
1199 if (shadow_regs[0] == 0x91)
1200 {
1201 sx = shadow_regs[0x67] * 256 + shadow_regs[0x66];
1202 ex = shadow_regs[0x6d] * 256 + shadow_regs[0x6c];
1203 DBG (7, "startx=%d, endx=%d, pixels=%d, coef=%d, r2f=0x%02x\n", sx, ex,
1204 ex - sx, dev->shadow_regs[0x7a], shadow_regs[0x2f]);
1205 sy = shadow_regs[0x61] * 256 + shadow_regs[0x60];
1206 ey = shadow_regs[0x63] * 256 + shadow_regs[0x62];
1207 DBG (7, "starty=%d, endy=%d, lines=%d\n", sy, ey, ey - sy);
1208 }
1209
1210 /* we use register 0xb0 to identify details about models */
1211 /* this register isn't overwritten during normal operation */
1212 if (shadow_regs[0xb0] == 0x2c && dev->model.sensor_type == X1100_B2_SENSOR)
1213 {
1214 variant = shadow_regs[0xb0];
1215 }
1216 /* now the same with register 0x10 */
1217 /* which most likely signals USB2.0/USB1.1 */
1218 if ((dev->model.sensor_type == X1200_SENSOR) && (shadow_regs[0x10] == 0x97))
1219 {
1220 variant = shadow_regs[0x10];
1221 }
1222
1223 /* if find a case where default model given is inappropriate, reassign it
1224 * since we have now the information to get the real one.
1225 * We could avoid this if attach() did open and read registers, not init */
1226 if (variant != 0)
1227 {
1228 DBG (3,
1229 "sanei_lexmark_low_open_device: reassign model/sensor for variant 0x%02x\n",
1230 variant);
1231 sanei_lexmark_low_assign_model (dev, dev->sane.name,
1232 dev->model.vendor_id,
1233 dev->model.product_id, variant);
1234 /* since model has changed, run init again */
1235 sanei_lexmark_low_init (dev);
1236 }
1237 DBG (2, "sanei_lexmark_low_open_device: end\n");
1238 return result;
1239 }
1240
1241 void
sanei_lexmark_low_close_device(Lexmark_Device * dev)1242 sanei_lexmark_low_close_device (Lexmark_Device * dev)
1243 {
1244 /* put scanner in idle state */
1245 lexmark_low_set_idle (dev->devnum);
1246
1247 /* This function calls the Sane USB library to close this usb device */
1248 #ifndef FAKE_USB
1249 sanei_usb_close (dev->devnum);
1250 #endif
1251 return;
1252 }
1253
1254
1255 /* This function writes the contents of the given registers to the
1256 scanner. */
1257 SANE_Status
low_write_all_regs(SANE_Int devnum,SANE_Byte * regs)1258 low_write_all_regs (SANE_Int devnum, SANE_Byte * regs)
1259 {
1260 int i;
1261 SANE_Status status;
1262 size_t size;
1263 static SANE_Byte command_block1[0xb7];
1264 static SANE_Byte command_block2[0x4f];
1265 command_block1[0] = 0x88;
1266 command_block1[1] = 0x00;
1267 command_block1[2] = 0x00;
1268 command_block1[3] = 0xb3;
1269 for (i = 0; i < 0xb3; i++)
1270 {
1271 command_block1[i + 4] = regs[i];
1272 }
1273 command_block2[0] = 0x88;
1274 command_block2[1] = 0xb4;
1275 command_block2[2] = 0x00;
1276 command_block2[3] = 0x4b;
1277 for (i = 0; i < 0x4b; i++)
1278 {
1279 command_block2[i + 4] = regs[i + 0xb4];
1280 }
1281 size = 0xb7;
1282
1283 #ifdef DEEP_DEBUG
1284 fprintf (stderr, "write_all(0x00,255)=");
1285 for (i = 0; i < 255; i++)
1286 {
1287 fprintf (stderr, "0x%02x ", regs[i]);
1288 }
1289 fprintf (stderr, "\n");
1290 #endif
1291
1292 status = low_usb_bulk_write (devnum, command_block1, &size);
1293 if (status != SANE_STATUS_GOOD)
1294 return status;
1295 size = 0x4f;
1296 status = low_usb_bulk_write (devnum, command_block2, &size);
1297 if (status != SANE_STATUS_GOOD)
1298 return status;
1299 return SANE_STATUS_GOOD;
1300 }
1301
1302
1303 SANE_Bool
low_is_home_line(Lexmark_Device * dev,unsigned char * buffer)1304 low_is_home_line (Lexmark_Device * dev, unsigned char *buffer)
1305 {
1306 /*
1307 This function assumes the buffer has a size of 2500 bytes.It is
1308 destructive to the buffer.
1309
1310 Here is what it does:
1311
1312 Go through the buffer finding low and high values, which are computed by
1313 comparing to the average:
1314 average = (lowest value + highest value)/2
1315 High bytes are changed to 0xFF (white), lower or equal bytes are changed
1316 to 0x00 (black),so that the buffer only contains white (0xFF) or black
1317 (0x00) values.
1318
1319 Next, we go through the buffer. We use a tolerance of 5 bytes on each end
1320 of the buffer and check a region from bytes 5 to 2495. We start assuming
1321 we are in a white region and look for the start of a black region. We save
1322 this index as the transition from white to black. We also save where we
1323 change from black back to white. We continue checking for transitions
1324 until the end of the check region. If we don't have exactly two
1325 transitions when we reach the end we return SANE_FALSE.
1326
1327 The final check compares the transition indices to the nominal values
1328 plus or minus the tolerance. For the first transition (white to black
1329 index) the value must lie in the range 1235-30 (1205) to 1235+30 (1265).
1330 For the second transition (black to white) the value must lie in the range
1331 1258-30 (1228) to 1258+30 (1288). If the indices are out of range we
1332 return SANE_FALSE. Otherwise, we return SANE_TRUE.
1333 */
1334
1335
1336 unsigned char max_byte = 0;
1337 unsigned char min_byte = 0xFF;
1338 unsigned char average;
1339 int i;
1340 int home_point1;
1341 int home_point2;
1342 region_type region;
1343 int transition_counter;
1344 int index1 = 0;
1345 int index2 = 0;
1346 int low_range, high_range;
1347
1348 #ifdef DEEP_DEBUG
1349 static int numero = 0;
1350 char titre[80];
1351 FILE *trace = NULL;
1352 sprintf (titre, "lgn%03d.pnm", numero);
1353 trace = fopen (titre, "wb");
1354 if (trace)
1355 {
1356 fprintf (trace, "P5\n2500 1\n255\n");
1357 fwrite (buffer, 2500, 1, trace);
1358 fclose (trace);
1359 }
1360 numero++;
1361 #endif
1362
1363 DBG (15, "low_is_home_line: start\n");
1364 /* Find the max and the min */
1365 for (i = 0; i < 2500; i++)
1366 {
1367 if (*(buffer + i) > max_byte)
1368 max_byte = *(buffer + i);
1369 if (*(buffer + i) < min_byte)
1370 min_byte = *(buffer + i);
1371 }
1372
1373 /* The average */
1374 average = ((max_byte + min_byte) / 2);
1375
1376 /* Set bytes as white (0xFF) or black (0x00) */
1377 for (i = 0; i < 2500; i++)
1378 {
1379 if (*(buffer + i) > average)
1380 *(buffer + i) = 0xFF;
1381 else
1382 *(buffer + i) = 0x00;
1383 }
1384
1385 region = white;
1386 transition_counter = 0;
1387
1388 /* Go through the check region - bytes 5 to 2495 */
1389 /* XXX STEF XXX shrink the area to where the dot should be
1390 * +-100 around the 1250 expected location */
1391 for (i = 1150; i <= 1350; i++)
1392 {
1393 /* Check for transition to black */
1394 if ((region == white) && (*(buffer + i) == 0))
1395 {
1396 if (transition_counter < 2)
1397 {
1398 region = black;
1399 index1 = i;
1400 transition_counter++;
1401 }
1402 else
1403 {
1404 DBG (15, "low_is_home_line: no transition to black \n");
1405 return SANE_FALSE;
1406 }
1407 }
1408 /* Check for transition to white */
1409 else if ((region == black) && (*(buffer + i) == 0xFF))
1410 {
1411 if (transition_counter < 2)
1412 {
1413 region = white;
1414 index2 = i;
1415 transition_counter++;
1416 }
1417 else
1418 {
1419 DBG (15, "low_is_home_line: no transition to white \n");
1420 return SANE_FALSE;
1421 }
1422 }
1423 }
1424
1425 /* Check that the number of transitions is 2 */
1426 if (transition_counter != 2)
1427 {
1428 DBG (15, "low_is_home_line: transitions!=2 (%d)\n", transition_counter);
1429 return SANE_FALSE;
1430 }
1431
1432
1433
1434
1435 /* Check that the 1st index is in range */
1436 home_point1 = dev->model.HomeEdgePoint1;
1437 low_range = home_point1 - HomeTolerance;
1438 high_range = home_point1 + HomeTolerance;
1439
1440 if ((index1 < low_range) || (index1 > high_range))
1441 {
1442 DBG (15, "low_is_home_line: index1=%d out of range\n", index1);
1443 return SANE_FALSE;
1444 }
1445
1446
1447 /* Check that the 2nd index is in range */
1448 home_point2 = dev->model.HomeEdgePoint2;
1449 low_range = home_point2 - HomeTolerance;
1450 high_range = home_point2 + HomeTolerance;
1451
1452 if ((index2 < low_range) || (index2 > high_range))
1453 {
1454 DBG (15, "low_is_home_line: index2=%d out of range.\n", index2);
1455 return SANE_FALSE;
1456 }
1457
1458 /* We made it this far, so its a good home line. Return True */
1459 DBG (15, "low_is_home_line: success\n");
1460 return SANE_TRUE;
1461 }
1462
1463 void
sanei_lexmark_low_move_fwd(SANE_Int distance,Lexmark_Device * dev,SANE_Byte * regs)1464 sanei_lexmark_low_move_fwd (SANE_Int distance, Lexmark_Device * dev,
1465 SANE_Byte * regs)
1466 {
1467 /*
1468 This function moves the scan head forward with the highest vertical
1469 resolution of 1200dpi. The distance moved is given by the distance
1470 parameter.
1471
1472 As an example, given a distance parameter of 600, the scan head will
1473 move 600/1200", or 1/2" forward.
1474 */
1475
1476 static SANE_Byte pollstopmoving_command_block[] =
1477 { 0x80, 0xb3, 0x00, 0x01 };
1478
1479
1480 size_t cmd_size;
1481 SANE_Int devnum;
1482 SANE_Bool scan_head_moving;
1483 SANE_Byte read_result;
1484
1485 DBG (2, "sanei_lexmark_low_move_fwd: \n");
1486 devnum = dev->devnum;
1487
1488
1489 /* registers set-up */
1490 regs[0x2c] = 0x00;
1491 regs[0x2d] = 0x41;
1492 regs[0x65] = 0x80;
1493 switch (dev->model.sensor_type)
1494 {
1495 case X74_SENSOR:
1496 rts88xx_set_scan_frequency (regs, 0);
1497 regs[0x93] = 0x06;
1498 break;
1499 case X1100_B2_SENSOR:
1500 regs[0x8b] = 0x00;
1501 regs[0x8c] = 0x00;
1502 regs[0x93] = 0x06;
1503 break;
1504 case X1100_2C_SENSOR:
1505 rts88xx_set_scan_frequency (regs, 0);
1506 regs[0x93] = 0x06;
1507 break;
1508 case A920_SENSOR:
1509 rts88xx_set_scan_frequency (regs, 0);
1510 regs[0x8b] = 0xff;
1511 regs[0x8c] = 0x02;
1512 regs[0x93] = 0x0e;
1513 break;
1514 case X1200_SENSOR:
1515 dev->shadow_regs[0x2d] = 0x01;
1516 rts88xx_set_scan_frequency (regs, 0);
1517 break;
1518 case X1200_USB2_SENSOR:
1519 dev->shadow_regs[0x2d] = 0x4f;
1520 rts88xx_set_scan_frequency (regs, 0);
1521 break;
1522 }
1523
1524 /* set grayscale scan + nodata/nochannel? */
1525 regs[0x2f] = 0xa1;
1526
1527 /* set ? */
1528 regs[0x34] = 0x50;
1529 regs[0x35] = 0x01;
1530 regs[0x36] = 0x50;
1531 regs[0x37] = 0x01;
1532 regs[0x38] = 0x50;
1533 /* set motor resolution divisor */
1534 regs[0x39] = 0x00;
1535 /* set vertical start/end positions */
1536 regs[0x60] = LOBYTE (distance - 1);
1537 regs[0x61] = HIBYTE (distance - 1);
1538 regs[0x62] = LOBYTE (distance);
1539 regs[0x63] = HIBYTE (distance);
1540 /* set horizontal start position */
1541 regs[0x66] = 0x64;
1542 regs[0x67] = 0x00;
1543 /* set horizontal end position */
1544 regs[0x6c] = 0xc8;
1545 regs[0x6d] = 0x00;
1546 /* set horizontal resolution */
1547 regs[0x79] = 0x40;
1548 regs[0x7a] = 0x01;
1549 /* don't buffer data for this scan */
1550 regs[0xb2] = 0x04;
1551 /* Motor enable & Coordinate space denominator */
1552 regs[0xc3] = 0x81;
1553 /* Movement direction & step size */
1554 regs[0xc6] = 0x09;
1555 /* ? */
1556 regs[0x80] = 0x00;
1557 regs[0x81] = 0x00;
1558 regs[0x82] = 0x00;
1559 regs[0xc5] = 0x0a;
1560
1561
1562 switch (dev->model.motor_type)
1563 {
1564 case X1100_MOTOR:
1565 case A920_MOTOR:
1566 /* step size range2 */
1567 regs[0xc9] = 0x3b;
1568 /* ? */
1569 regs[0xca] = 0x0a;
1570 /* motor curve stuff */
1571 regs[0xe0] = 0x00;
1572 regs[0xe1] = 0x00;
1573 regs[0xe4] = 0x00;
1574 regs[0xe5] = 0x00;
1575 regs[0xe7] = 0x00;
1576 regs[0xe8] = 0x00;
1577 regs[0xe2] = 0x09;
1578 regs[0xe3] = 0x1a;
1579 regs[0xe6] = 0xdc;
1580 regs[0xe9] = 0x1b;
1581 regs[0xec] = 0x07;
1582 regs[0xef] = 0x03;
1583 break;
1584 case X74_MOTOR:
1585 regs[0xc5] = 0x41;
1586 /* step size range2 */
1587 regs[0xc9] = 0x39;
1588 /* ? */
1589 regs[0xca] = 0x40;
1590 /* motor curve stuff */
1591 regs[0xe0] = 0x00;
1592 regs[0xe1] = 0x00;
1593 regs[0xe2] = 0x09;
1594 regs[0xe3] = 0x1a;
1595 regs[0xe4] = 0x00;
1596 regs[0xe5] = 0x00;
1597 regs[0xe6] = 0x64;
1598 regs[0xe7] = 0x00;
1599 regs[0xe8] = 0x00;
1600 regs[0xe9] = 0x32;
1601 regs[0xec] = 0x0c;
1602 regs[0xef] = 0x08;
1603 break;
1604 }
1605
1606
1607 /* prepare for register write */
1608 low_clr_c6 (devnum);
1609 low_stop_mvmt (devnum);
1610
1611 /* Move Forward without scanning: */
1612 regs[0x32] = 0x00;
1613 low_write_all_regs (devnum, regs);
1614 regs[0x32] = 0x40;
1615 low_write_all_regs (devnum, regs);
1616
1617 /* Stop scanner - clear reg 0xb3: */
1618 /* low_stop_mvmt (devnum); */
1619
1620 rts88xx_commit (devnum, regs[0x2c]);
1621
1622 /* Poll for scanner stopped - return value(3:0) = 0: */
1623 scan_head_moving = SANE_TRUE;
1624 while (scan_head_moving)
1625 {
1626 #ifdef FAKE_USB
1627 scan_head_moving = SANE_FALSE;
1628 #else
1629 cmd_size = 0x04;
1630 low_usb_bulk_write (devnum, pollstopmoving_command_block, &cmd_size);
1631 cmd_size = 0x1;
1632 low_usb_bulk_read (devnum, &read_result, &cmd_size);
1633 if ((read_result & 0xF) == 0x0)
1634 {
1635 scan_head_moving = SANE_FALSE;
1636 }
1637 #endif
1638 }
1639
1640 /* this is needed to find the start line properly */
1641 if (dev->model.sensor_type == X74_SENSOR)
1642 low_stop_mvmt (devnum);
1643
1644 DBG (2, "sanei_lexmark_low_move_fwd: end.\n");
1645 }
1646
1647 SANE_Bool
sanei_lexmark_low_search_home_fwd(Lexmark_Device * dev)1648 sanei_lexmark_low_search_home_fwd (Lexmark_Device * dev)
1649 {
1650 /* This function actually searches backwards one line looking for home */
1651
1652 SANE_Int devnum;
1653 int i;
1654 SANE_Byte poll_result[3];
1655 SANE_Byte *buffer;
1656 SANE_Byte temp_byte;
1657
1658 static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 };
1659
1660 static SANE_Byte command5_block[] = { 0x91, 0x00, 0x09, 0xc4 };
1661
1662 size_t cmd_size;
1663 SANE_Bool got_line;
1664 SANE_Bool ret_val;
1665
1666 devnum = dev->devnum;
1667
1668 DBG (2, "sanei_lexmark_low_search_home_fwd:\n");
1669
1670 /* set up registers according to the sensor type */
1671 switch (dev->model.sensor_type)
1672 {
1673 case X74_SENSOR:
1674 dev->shadow_regs[0x2c] = 0x03;
1675 dev->shadow_regs[0x2d] = 0x45;
1676 dev->shadow_regs[0x2f] = 0x21;
1677 dev->shadow_regs[0x30] = 0x48;
1678 dev->shadow_regs[0x31] = 0x06;
1679 dev->shadow_regs[0x34] = 0x05;
1680 dev->shadow_regs[0x35] = 0x05;
1681 dev->shadow_regs[0x36] = 0x09;
1682 dev->shadow_regs[0x37] = 0x09;
1683 dev->shadow_regs[0x38] = 0x0d;
1684 dev->shadow_regs[0x40] = 0x80;
1685 dev->shadow_regs[0x75] = 0x00;
1686 dev->shadow_regs[0x8b] = 0xff;
1687 dev->shadow_regs[0x93] = 0x06;
1688 break;
1689 case X1100_B2_SENSOR:
1690 dev->shadow_regs[0x2c] = 0x0f;
1691 dev->shadow_regs[0x2d] = 0x51;
1692 dev->shadow_regs[0x2f] = 0x21;
1693 dev->shadow_regs[0x34] = 0x04;
1694 dev->shadow_regs[0x35] = 0x04;
1695 dev->shadow_regs[0x36] = 0x08;
1696 dev->shadow_regs[0x37] = 0x08;
1697 dev->shadow_regs[0x38] = 0x0b;
1698 dev->shadow_regs[0x93] = 0x06;
1699 break;
1700 case X1100_2C_SENSOR:
1701 dev->shadow_regs[0x2c] = 0x0d;
1702 dev->shadow_regs[0x2d] = 0x4f;
1703 dev->shadow_regs[0x34] = 0x05;
1704 dev->shadow_regs[0x35] = 0x05;
1705 dev->shadow_regs[0x36] = 0x09;
1706 dev->shadow_regs[0x37] = 0x09;
1707 dev->shadow_regs[0x38] = 0x0d;
1708 dev->shadow_regs[0x40] = 0x80;
1709 dev->shadow_regs[0x72] = 0x35;
1710 dev->shadow_regs[0x74] = 0x4e;
1711
1712 dev->shadow_regs[0x85] = 0x20; /* 05 */
1713 dev->shadow_regs[0x86] = 0x00; /* 05 */
1714 dev->shadow_regs[0x87] = 0x00; /* 05 */
1715 dev->shadow_regs[0x88] = 0x00; /* 45 */
1716 dev->shadow_regs[0x89] = 0x00;
1717 dev->shadow_regs[0x8b] = 0xff;
1718
1719 dev->shadow_regs[0x93] = 0x06; /* 0e */
1720
1721 dev->shadow_regs[0x75] = 0x00; /* */
1722 dev->shadow_regs[0x91] = 0x00; /* 60 */
1723 dev->shadow_regs[0x92] = 0x00; /* 8d */
1724 dev->shadow_regs[0xb1] = 0x00; /* */
1725 dev->shadow_regs[0xc5] = 0x00; /* */
1726 dev->shadow_regs[0xca] = 0x00; /* */
1727 dev->shadow_regs[0xc3] = 0x01; /* */
1728 break;
1729 case A920_SENSOR:
1730 dev->shadow_regs[0x2c] = 0x0d;
1731 dev->shadow_regs[0x2d] = 0x4f;
1732 dev->shadow_regs[0x34] = 0x05;
1733 dev->shadow_regs[0x35] = 0x05;
1734 dev->shadow_regs[0x36] = 0x09;
1735 dev->shadow_regs[0x37] = 0x09;
1736 dev->shadow_regs[0x38] = 0x0d;
1737 dev->shadow_regs[0x40] = 0x80;
1738 dev->shadow_regs[0x72] = 0x35;
1739 dev->shadow_regs[0x74] = 0x4e;
1740 dev->shadow_regs[0x85] = 0x05;
1741 dev->shadow_regs[0x88] = 0x45;
1742 dev->shadow_regs[0x89] = 0x00;
1743 dev->shadow_regs[0x8b] = 0xff;
1744 dev->shadow_regs[0x91] = 0x60;
1745 dev->shadow_regs[0x92] = 0x8d;
1746 dev->shadow_regs[0x93] = 0x0e;
1747 break;
1748 case X1200_SENSOR:
1749 dev->shadow_regs[0x2c] = 0x01;
1750 dev->shadow_regs[0x2d] = 0x03;
1751 dev->shadow_regs[0x34] = 0x04;
1752 dev->shadow_regs[0x35] = 0x04;
1753 dev->shadow_regs[0x36] = 0x08;
1754 dev->shadow_regs[0x37] = 0x08;
1755 dev->shadow_regs[0x38] = 0x0b;
1756 dev->shadow_regs[0x66] = 0x88;
1757 dev->shadow_regs[0x6c] = 0x10;
1758 dev->shadow_regs[0x6d] = 0x14;
1759 dev->shadow_regs[0x75] = 0x00;
1760 dev->shadow_regs[0x93] = 0x06;
1761 dev->shadow_regs[0xc5] = 0x00;
1762 dev->shadow_regs[0xca] = 0x00;
1763 break;
1764 case X1200_USB2_SENSOR:
1765 dev->shadow_regs[0x0b] = 0x70;
1766 dev->shadow_regs[0x0c] = 0x28;
1767 dev->shadow_regs[0x0d] = 0xa4;
1768 dev->shadow_regs[0x2c] = 0x0d;
1769 dev->shadow_regs[0x2d] = 0x4f;
1770 dev->shadow_regs[0x2f] = 0x21;
1771 dev->shadow_regs[0x32] = 0x40;
1772 dev->shadow_regs[0x34] = 0x05;
1773 dev->shadow_regs[0x35] = 0x05;
1774 dev->shadow_regs[0x36] = 0x09;
1775 dev->shadow_regs[0x37] = 0x09;
1776 dev->shadow_regs[0x38] = 0x0d;
1777 dev->shadow_regs[0x3a] = 0x20;
1778 dev->shadow_regs[0x3b] = 0x37;
1779 dev->shadow_regs[0x40] = 0x80;
1780 dev->shadow_regs[0x47] = 0x01;
1781 dev->shadow_regs[0x48] = 0x1a;
1782 dev->shadow_regs[0x49] = 0x5b;
1783 dev->shadow_regs[0x4a] = 0x1b;
1784 dev->shadow_regs[0x4b] = 0x5b;
1785 dev->shadow_regs[0x4c] = 0x05;
1786 dev->shadow_regs[0x4d] = 0x3f;
1787 dev->shadow_regs[0x75] = 0x00;
1788 dev->shadow_regs[0x85] = 0x03;
1789 dev->shadow_regs[0x86] = 0x33;
1790 dev->shadow_regs[0x87] = 0x8f;
1791 dev->shadow_regs[0x88] = 0x34;
1792 dev->shadow_regs[0x8b] = 0xff;
1793 dev->shadow_regs[0x8e] = 0x60;
1794 dev->shadow_regs[0x8f] = 0x80;
1795 dev->shadow_regs[0x91] = 0x59;
1796 dev->shadow_regs[0x92] = 0x10;
1797 dev->shadow_regs[0x93] = 0x06;
1798 dev->shadow_regs[0xa3] = 0x0d;
1799 dev->shadow_regs[0xa4] = 0x5e;
1800 dev->shadow_regs[0xa5] = 0x23;
1801 dev->shadow_regs[0xb1] = 0x07;
1802 dev->shadow_regs[0xc2] = 0x80;
1803 dev->shadow_regs[0xc5] = 0x00;
1804 dev->shadow_regs[0xca] = 0x00;
1805 break;
1806 }
1807 dev->shadow_regs[0x65] = 0x80;
1808 dev->shadow_regs[0x8c] = 0x02;
1809 dev->shadow_regs[0x8d] = 0x01;
1810 dev->shadow_regs[0xb2] = 0x00;
1811 dev->shadow_regs[0xed] = 0x00;
1812 dev->shadow_regs[0xee] = 0x00;
1813
1814 rts88xx_set_gain (dev->shadow_regs, dev->sensor->default_gain,
1815 dev->sensor->default_gain, dev->sensor->default_gain);
1816 rts88xx_set_offset (dev->shadow_regs, 0x80, 0x80, 0x80);
1817
1818 /* set grayscale scan */
1819 rts88xx_set_gray_scan (dev->shadow_regs);
1820
1821 /* set motor resolution divisor */
1822 dev->shadow_regs[0x39] = 0x07;
1823
1824 /* set vertical start/end positions */
1825 dev->shadow_regs[0x60] = 0x01;
1826 dev->shadow_regs[0x61] = 0x00;
1827 dev->shadow_regs[0x62] = 0x02;
1828 dev->shadow_regs[0x63] = 0x00;
1829
1830 /* set # of head moves per CIS read */
1831 rts88xx_set_scan_frequency (dev->shadow_regs, 1);
1832
1833 /* set horizontal start position */
1834 dev->shadow_regs[0x66] = 0x6a; /* 0x88 for X1200 */
1835 dev->shadow_regs[0x67] = 0x00;
1836 /* set horizontal end position */
1837 dev->shadow_regs[0x6c] = 0xf2; /* 0x1410 for X1200 */
1838 dev->shadow_regs[0x6d] = 0x13;
1839 /* set horizontal resolution */
1840 dev->shadow_regs[0x79] = 0x40;
1841 dev->shadow_regs[0x7a] = 0x02;
1842 /* Motor disable & Coordinate space denominator */
1843 dev->shadow_regs[0xc3] = 0x01;
1844 /* Movement direction & step size */
1845 dev->shadow_regs[0xc6] = 0x01;
1846
1847 switch (dev->model.motor_type)
1848 {
1849 case A920_MOTOR:
1850 case X1100_MOTOR:
1851 /* step size range2 */
1852 dev->shadow_regs[0xc9] = 0x3b;
1853 /* step size range0 */
1854 dev->shadow_regs[0xe2] = 0x01;
1855 /* ? */
1856 dev->shadow_regs[0xe3] = 0x03;
1857 break;
1858 case X74_MOTOR:
1859 dev->shadow_regs[0xc4] = 0x20;
1860 dev->shadow_regs[0xc5] = 0x00;
1861 dev->shadow_regs[0xc8] = 0x04;
1862 /* step size range2 */
1863 dev->shadow_regs[0xc9] = 0x39;
1864 dev->shadow_regs[0xca] = 0x00;
1865 /* motor curve stuff */
1866 dev->shadow_regs[0xe0] = 0x29;
1867 dev->shadow_regs[0xe1] = 0x17;
1868 dev->shadow_regs[0xe2] = 0x8f;
1869 dev->shadow_regs[0xe3] = 0x06;
1870 dev->shadow_regs[0xe4] = 0x61;
1871 dev->shadow_regs[0xe5] = 0x16;
1872 dev->shadow_regs[0xe6] = 0x64;
1873 dev->shadow_regs[0xe7] = 0xb5;
1874 dev->shadow_regs[0xe8] = 0x08;
1875 dev->shadow_regs[0xe9] = 0x32;
1876 dev->shadow_regs[0xec] = 0x0c;
1877 dev->shadow_regs[0xef] = 0x08;
1878 break;
1879 }
1880
1881 /* Stop the scanner */
1882 low_stop_mvmt (devnum);
1883
1884 /* write regs out twice */
1885 dev->shadow_regs[0x32] = 0x00;
1886 low_write_all_regs (devnum, dev->shadow_regs);
1887 dev->shadow_regs[0x32] = 0x40;
1888 low_write_all_regs (devnum, dev->shadow_regs);
1889
1890 /* Start Scan */
1891 rts88xx_commit (devnum, dev->shadow_regs[0x2c]);
1892
1893 /* Poll the available byte count until not 0 */
1894 got_line = SANE_FALSE;
1895 while (!got_line)
1896 {
1897 cmd_size = 4;
1898 low_usb_bulk_write (devnum, command4_block, &cmd_size);
1899 cmd_size = 0x3;
1900 low_usb_bulk_read (devnum, poll_result, &cmd_size);
1901 if (!
1902 (poll_result[0] == 0 && poll_result[1] == 0 && poll_result[2] == 0))
1903 {
1904 /* if result != 00 00 00 we got data */
1905 got_line = SANE_TRUE;
1906 }
1907 }
1908
1909 /* create buffer for scan data */
1910 buffer = calloc (2500, sizeof (char));
1911 if (buffer == NULL)
1912 {
1913 return SANE_FALSE;
1914 }
1915
1916 /* Tell the scanner to send the data */
1917 /* Write: 91 00 09 c4 */
1918 cmd_size = 4;
1919 low_usb_bulk_write (devnum, command5_block, &cmd_size);
1920 /* Read it */
1921 cmd_size = 0x09c4;
1922 low_usb_bulk_read (devnum, buffer, &cmd_size);
1923
1924 /* Reverse order of bytes in words of buffer */
1925 for (i = 0; i < 2500; i = i + 2)
1926 {
1927 temp_byte = *(buffer + i);
1928 *(buffer + i) = *(buffer + i + 1);
1929 *(buffer + i + 1) = temp_byte;
1930 }
1931
1932 /* check for home position */
1933 ret_val = low_is_home_line (dev, buffer);
1934
1935 if (ret_val)
1936 DBG (2, "sanei_lexmark_low_search_home_fwd: !!!HOME POSITION!!!\n");
1937
1938 /* free the buffer */
1939 free (buffer);
1940 DBG (2, "sanei_lexmark_low_search_home_fwd: end.\n");
1941
1942 return ret_val;
1943 }
1944
1945 SANE_Bool
sanei_lexmark_low_search_home_bwd(Lexmark_Device * dev)1946 sanei_lexmark_low_search_home_bwd (Lexmark_Device * dev)
1947 {
1948 /* This function must only be called if the scan head is past the home dot.
1949 It could damage the scanner if not.
1950
1951 This function tells the scanner to do a grayscale scan backwards with a
1952 300dpi resolution. It reads 2500 bytes of data between horizontal
1953 coordinates 0x6a and 0x13f2.
1954
1955 The scan is set to read between vertical coordinates from 0x0a to 0x0f46,
1956 or 3900 lines. This equates to 13" at 300dpi, so we must stop the scan
1957 before it bangs against the end. A line limit is set so that a maximum of
1958 0x0F3C (13"*300dpi) lines can be read.
1959
1960 To read the scan data we create a buffer space large enough to hold 10
1961 lines of data. For each read we poll twice, ignoring the first poll. This
1962 is required for timing. We repeat the double poll until there is data
1963 available. The number of lines (or number of buffers in our buffer space)
1964 is calculated from the size of the data available from the scanner. The
1965 number of buffers is calculated as the space required to hold 1.5 times
1966 the size of the data available from the scanner.
1967
1968 After data is read from the scanner each line is checked if it is on the
1969 home dot. Lines are continued to be read until we are no longer on the home
1970 dot. */
1971
1972
1973 SANE_Int devnum;
1974 SANE_Status status;
1975 int i, j;
1976 SANE_Byte poll_result[3];
1977 SANE_Byte *buffer;
1978 SANE_Byte *buffer_start;
1979 SANE_Byte temp_byte;
1980
1981 SANE_Int buffer_count = 0;
1982 SANE_Int size_requested;
1983 SANE_Int size_returned;
1984 SANE_Int no_of_buffers;
1985 SANE_Int buffer_limit = 0xF3C;
1986
1987 SANE_Int high_byte, mid_byte, low_byte;
1988 SANE_Int home_line_count;
1989 SANE_Bool in_home_region;
1990
1991 static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 };
1992
1993 static SANE_Byte command5_block[] = { 0x91, 0x00, 0xff, 0xc0 };
1994 #ifdef DEEP_DEBUG
1995 FILE *img = NULL;
1996 #endif
1997
1998 size_t cmd_size;
1999 SANE_Bool got_line;
2000
2001 devnum = dev->devnum;
2002
2003 DBG (2, "sanei_lexmark_low_search_home_bwd:\n");
2004
2005 /* set up registers */
2006 switch (dev->model.sensor_type)
2007 {
2008 case X74_SENSOR:
2009 dev->shadow_regs[0x2c] = 0x03;
2010 dev->shadow_regs[0x2d] = 0x45;
2011 dev->shadow_regs[0x34] = 0x09;
2012 dev->shadow_regs[0x35] = 0x09;
2013 dev->shadow_regs[0x36] = 0x11;
2014 dev->shadow_regs[0x37] = 0x11;
2015 dev->shadow_regs[0x38] = 0x19;
2016 dev->shadow_regs[0x85] = 0x00;
2017 dev->shadow_regs[0x93] = 0x06;
2018 dev->shadow_regs[0x40] = 0x80;
2019 /* important for detection of b/w transitions */
2020 dev->shadow_regs[0x75] = 0x00;
2021 dev->shadow_regs[0x8b] = 0xff;
2022 break;
2023 case X1100_B2_SENSOR:
2024 dev->shadow_regs[0x2c] = 0x0f;
2025 dev->shadow_regs[0x2d] = 0x51;
2026 dev->shadow_regs[0x34] = 0x07;
2027 dev->shadow_regs[0x35] = 0x07;
2028 dev->shadow_regs[0x36] = 0x0f;
2029 dev->shadow_regs[0x37] = 0x0f;
2030 dev->shadow_regs[0x38] = 0x15;
2031 dev->shadow_regs[0x85] = 0x20;
2032 dev->shadow_regs[0x93] = 0x06;
2033 break;
2034 case X1100_2C_SENSOR:
2035 dev->shadow_regs[0x2c] = 0x0d;
2036 dev->shadow_regs[0x2d] = 0x4f;
2037 dev->shadow_regs[0x34] = 0x09;
2038 dev->shadow_regs[0x35] = 0x09;
2039 dev->shadow_regs[0x36] = 0x11;
2040 dev->shadow_regs[0x37] = 0x11;
2041 dev->shadow_regs[0x38] = 0x19;
2042 dev->shadow_regs[0x85] = 0x20;
2043 dev->shadow_regs[0x93] = 0x06;
2044 break;
2045 case A920_SENSOR:
2046 dev->shadow_regs[0x2c] = 0x0d;
2047 dev->shadow_regs[0x2d] = 0x4f;
2048 dev->shadow_regs[0x34] = 0x09;
2049 dev->shadow_regs[0x35] = 0x09;
2050 dev->shadow_regs[0x36] = 0x11;
2051 dev->shadow_regs[0x37] = 0x11;
2052 dev->shadow_regs[0x38] = 0x19;
2053 dev->shadow_regs[0x85] = 0x05;
2054 dev->shadow_regs[0x93] = 0x0e;
2055 break;
2056 case X1200_SENSOR:
2057 dev->shadow_regs[0x2c] = 0x01;
2058 dev->shadow_regs[0x2d] = 0x03;
2059 dev->shadow_regs[0x34] = 0x07;
2060 dev->shadow_regs[0x35] = 0x07;
2061 dev->shadow_regs[0x36] = 0x0f;
2062 dev->shadow_regs[0x37] = 0x0f;
2063 dev->shadow_regs[0x38] = 0x15;
2064 break;
2065
2066 case X1200_USB2_SENSOR:
2067 dev->shadow_regs[0x2c] = 0x0d;
2068 dev->shadow_regs[0x2d] = 0x4f;
2069 dev->shadow_regs[0x34] = 0x09;
2070 dev->shadow_regs[0x35] = 0x09;
2071 dev->shadow_regs[0x36] = 0x11;
2072 dev->shadow_regs[0x37] = 0x11;
2073 dev->shadow_regs[0x38] = 0x19;
2074 dev->shadow_regs[0x85] = 0x03;
2075 dev->shadow_regs[0x93] = 0x06;
2076 break;
2077 }
2078 rts88xx_set_gain (dev->shadow_regs, dev->sensor->default_gain,
2079 dev->sensor->default_gain, dev->sensor->default_gain);
2080 dev->shadow_regs[0x65] = 0x80;
2081 dev->shadow_regs[0x8b] = 0xff;
2082 dev->shadow_regs[0x8c] = 0x02;
2083 dev->shadow_regs[0xb2] = 0x00;
2084
2085 /* set calibration */
2086 rts88xx_set_offset (dev->shadow_regs, 0x80, 0x80, 0x80);
2087
2088 /* set grayscale scan */
2089 dev->shadow_regs[0x2f] = 0x21;
2090 /* set motor resolution divisor */
2091 dev->shadow_regs[0x39] = 0x03;
2092 /* set vertical start/end positions */
2093 dev->shadow_regs[0x60] = 0x0a;
2094 dev->shadow_regs[0x61] = 0x00;
2095 dev->shadow_regs[0x62] = 0x46;
2096 dev->shadow_regs[0x63] = 0x0f;
2097 /* set # of head moves per CIS read */
2098 rts88xx_set_scan_frequency (dev->shadow_regs, 2);
2099 /* set horizontal start position */
2100 dev->shadow_regs[0x66] = 0x6a; /* 0x88 for X1200 */
2101 dev->shadow_regs[0x67] = 0x00;
2102 /* set horizontal end position */
2103 dev->shadow_regs[0x6c] = 0xf2; /* 0x1410 for X1200, 13f2 for X1200/rev. 97 */
2104 dev->shadow_regs[0x6d] = 0x13;
2105 /* set horizontal resolution */
2106 dev->shadow_regs[0x79] = 0x40;
2107 dev->shadow_regs[0x7a] = 0x02;
2108
2109 /* Movement direction & step size */
2110 dev->shadow_regs[0xc6] = 0x01;
2111 /* Motor enable & Coordinate space denominator */
2112 dev->shadow_regs[0xc3] = 0x81;
2113
2114 switch (dev->model.motor_type)
2115 {
2116 case X74_MOTOR:
2117 dev->shadow_regs[0xc4] = 0x20;
2118 dev->shadow_regs[0xc5] = 0x00;
2119 dev->shadow_regs[0xc8] = 0x04;
2120 /* step size range2 */
2121 dev->shadow_regs[0xc9] = 0x39;
2122 dev->shadow_regs[0xca] = 0x00;
2123 /* motor curve stuff */
2124 dev->shadow_regs[0xe0] = 0x29;
2125 dev->shadow_regs[0xe1] = 0x17;
2126 dev->shadow_regs[0xe2] = 0x8f;
2127 dev->shadow_regs[0xe3] = 0x06;
2128 dev->shadow_regs[0xe4] = 0x61;
2129 dev->shadow_regs[0xe5] = 0x16;
2130 dev->shadow_regs[0xe6] = 0x64;
2131 dev->shadow_regs[0xe7] = 0xb5;
2132 dev->shadow_regs[0xe8] = 0x08;
2133 dev->shadow_regs[0xe9] = 0x32;
2134 dev->shadow_regs[0xec] = 0x0c;
2135 dev->shadow_regs[0xef] = 0x08;
2136 break;
2137 case A920_MOTOR:
2138 case X1100_MOTOR:
2139 /* ? */
2140 dev->shadow_regs[0xc5] = 0x19;
2141 /* step size range2 */
2142 dev->shadow_regs[0xc9] = 0x3a;
2143 /* ? */
2144 dev->shadow_regs[0xca] = 0x08;
2145 /* motor curve stuff */
2146 dev->shadow_regs[0xe0] = 0xe3;
2147 dev->shadow_regs[0xe1] = 0x18;
2148 dev->shadow_regs[0xe2] = 0x03;
2149 dev->shadow_regs[0xe3] = 0x06;
2150 dev->shadow_regs[0xe4] = 0x2b;
2151 dev->shadow_regs[0xe5] = 0x17;
2152 dev->shadow_regs[0xe6] = 0xdc;
2153 dev->shadow_regs[0xe7] = 0xb3;
2154 dev->shadow_regs[0xe8] = 0x07;
2155 dev->shadow_regs[0xe9] = 0x1b;
2156 dev->shadow_regs[0xec] = 0x07;
2157 dev->shadow_regs[0xef] = 0x03;
2158 break;
2159 }
2160
2161 /* Stop the scanner */
2162 low_stop_mvmt (devnum);
2163
2164 /* write regs out twice */
2165 dev->shadow_regs[0x32] = 0x00;
2166 low_write_all_regs (devnum, dev->shadow_regs);
2167 dev->shadow_regs[0x32] = 0x40;
2168 low_write_all_regs (devnum, dev->shadow_regs);
2169
2170 /* Start Scan */
2171 status = rts88xx_commit (devnum, dev->shadow_regs[0x2c]);
2172
2173 /* create buffer to hold up to 10 lines of scan data */
2174 buffer = calloc (10 * 2500, sizeof (char));
2175 if (buffer == NULL)
2176 {
2177 return SANE_FALSE;
2178 }
2179
2180 home_line_count = 0;
2181 in_home_region = SANE_FALSE;
2182
2183 #ifdef DEEP_DEBUG
2184 img = fopen ("find_bwd.pnm", "wb");
2185 fprintf (img, "P5\n2500 100\n255\n");
2186 #endif
2187 while (buffer_count < buffer_limit)
2188 {
2189 size_returned = 0;
2190 got_line = SANE_FALSE;
2191 while (!got_line)
2192 {
2193 /* always poll twice (needed for timing) - disregard 1st poll */
2194 cmd_size = 4;
2195 status = low_usb_bulk_write (devnum, command4_block, &cmd_size);
2196 if (status != SANE_STATUS_GOOD)
2197 return SANE_FALSE;
2198 cmd_size = 0x3;
2199 status = low_usb_bulk_read (devnum, poll_result, &cmd_size);
2200 if (status != SANE_STATUS_GOOD)
2201 return SANE_FALSE;
2202 cmd_size = 4;
2203 status = low_usb_bulk_write (devnum, command4_block, &cmd_size);
2204 if (status != SANE_STATUS_GOOD)
2205 return SANE_FALSE;
2206 cmd_size = 0x3;
2207 status = low_usb_bulk_read (devnum, poll_result, &cmd_size);
2208 if (status != SANE_STATUS_GOOD)
2209 return SANE_FALSE;
2210 if (!
2211 (poll_result[0] == 0 && poll_result[1] == 0
2212 && poll_result[2] == 0))
2213 {
2214 /* if result != 00 00 00 we got data */
2215 got_line = SANE_TRUE;
2216 high_byte = poll_result[2] << 16;
2217 mid_byte = poll_result[1] << 8;
2218 low_byte = poll_result[0];
2219 size_returned = high_byte + mid_byte + low_byte;
2220 }
2221 }
2222
2223 /*size_requested = size_returned;*/
2224 size_requested = 2500;
2225 no_of_buffers = size_returned * 3;
2226 no_of_buffers = no_of_buffers / 2500;
2227 no_of_buffers = no_of_buffers >> 1;
2228 /* force 1 buffer at a time to improve accuracy, which slow downs search */
2229 no_of_buffers = 1;
2230
2231 if (no_of_buffers < 1)
2232 no_of_buffers = 1;
2233 else if (no_of_buffers > 10)
2234 no_of_buffers = 10;
2235 buffer_count = buffer_count + no_of_buffers;
2236
2237 size_requested = no_of_buffers * 2500;
2238
2239 /* Tell the scanner to send the data */
2240 /* Write: 91 <size_requested> */
2241 command5_block[1] = (SANE_Byte) (size_requested >> 16);
2242 command5_block[2] = (SANE_Byte) (size_requested >> 8);
2243 command5_block[3] = (SANE_Byte) (size_requested & 0xFF);
2244
2245 cmd_size = 4;
2246 status = low_usb_bulk_write (devnum, command5_block, &cmd_size);
2247 if (status != SANE_STATUS_GOOD)
2248 return SANE_FALSE;
2249 /* Read it */
2250 cmd_size = size_requested;
2251 status = low_usb_bulk_read (devnum, buffer, &cmd_size);
2252 if (status != SANE_STATUS_GOOD)
2253 return SANE_FALSE;
2254 for (i = 0; i < no_of_buffers; i++)
2255 {
2256 buffer_start = buffer + (i * 2500);
2257 /* Reverse order of bytes in words of buffer */
2258 for (j = 0; j < 2500; j = j + 2)
2259 {
2260 temp_byte = *(buffer_start + j);
2261 *(buffer_start + j) = *(buffer_start + j + 1);
2262 *(buffer_start + j + 1) = temp_byte;
2263 }
2264 #ifdef DEEP_DEBUG
2265 fwrite (buffer + (i * 2500), 2500, 1, img);
2266 #endif
2267 if (low_is_home_line (dev, buffer_start))
2268 {
2269 home_line_count++;
2270 if (home_line_count > 7)
2271 in_home_region = SANE_TRUE;
2272 }
2273 if (in_home_region)
2274 {
2275 /* slow down scanning : on purpose backtracking */
2276 if (home_line_count)
2277 sleep (1);
2278 free (buffer);
2279 #ifdef DEEP_DEBUG
2280 fflush (img);
2281 i = ftell (img) / 2500;
2282 rewind (img);
2283 DBG (2, "sanei_lexmark_low_search_home_bwd: offset=%d\n", i);
2284 fprintf (img, "P5\n2500 %03d\n", i);
2285 fclose (img);
2286 #endif
2287 low_stop_mvmt (devnum);
2288 DBG (2,
2289 "sanei_lexmark_low_search_home_bwd: in home region, end.\n");
2290 return SANE_TRUE;
2291 }
2292 }
2293 } /* end while (buffer_count > buffer_limit); */
2294 free (buffer);
2295 #ifdef DEEP_DEBUG
2296 fflush (img);
2297 i = ftell (img) / 2500;
2298 rewind (img);
2299 fprintf (img, "P5\n2500 %03d\n", i);
2300 fclose (img);
2301 #endif
2302 low_stop_mvmt (devnum);
2303
2304 DBG (2, "sanei_lexmark_low_search_home_bwd: end.\n");
2305
2306 return SANE_FALSE;
2307 }
2308
2309 SANE_Status
low_get_start_loc(SANE_Int resolution,SANE_Int * vert_start,SANE_Int * hor_start,SANE_Int offset,Lexmark_Device * dev)2310 low_get_start_loc (SANE_Int resolution, SANE_Int * vert_start,
2311 SANE_Int * hor_start, SANE_Int offset,
2312 Lexmark_Device * dev)
2313 {
2314 SANE_Int start_600;
2315
2316 switch (dev->model.sensor_type)
2317 {
2318 case X1100_2C_SENSOR:
2319 case X1200_USB2_SENSOR:
2320 case A920_SENSOR:
2321 case X1200_SENSOR:
2322 start_600 = 195 - offset;
2323 *hor_start = 0x68;
2324 break;
2325 case X1100_B2_SENSOR:
2326 start_600 = 195 - offset;
2327 switch (resolution)
2328 {
2329 case 75:
2330 *hor_start = 0x68;
2331 break;
2332 case 150:
2333 *hor_start = 0x68;
2334 break;
2335 case 300:
2336 *hor_start = 0x6a;
2337 break;
2338 case 600:
2339 *hor_start = 0x6b;
2340 break;
2341 case 1200:
2342 *hor_start = 0x6b;
2343 break;
2344 default:
2345 /* If we're here we have an invalid resolution */
2346 return SANE_STATUS_INVAL;
2347 }
2348 break;
2349 case X74_SENSOR:
2350 start_600 = 268 - offset;
2351 switch (resolution)
2352 {
2353 case 75:
2354 *hor_start = 0x48;
2355 break;
2356 case 150:
2357 *hor_start = 0x48;
2358 break;
2359 case 300:
2360 *hor_start = 0x4a;
2361 break;
2362 case 600:
2363 *hor_start = 0x4b;
2364 break;
2365 default:
2366 /* If we're here we have an invalid resolution */
2367 return SANE_STATUS_INVAL;
2368 }
2369 break;
2370 default:
2371 /* If we're here we have an unknown dev->model.sensor_type */
2372 return SANE_STATUS_INVAL;
2373 }
2374 /* Calculate vertical start distance at 600dpi */
2375 switch (resolution)
2376 {
2377 case 75:
2378 *vert_start = start_600 / 8;
2379 break;
2380 case 150:
2381 *vert_start = start_600 / 4;
2382 break;
2383 case 300:
2384 *vert_start = start_600 / 2;
2385 break;
2386 case 600:
2387 *vert_start = start_600;
2388 break;
2389 case 1200:
2390 *vert_start = start_600 * 2;
2391 break;
2392 default:
2393 /* If we're here we have an invalid resolution */
2394 return SANE_STATUS_INVAL;
2395 }
2396
2397 return SANE_STATUS_GOOD;
2398 }
2399
2400 void
low_set_scan_area(SANE_Int res,SANE_Int tlx,SANE_Int tly,SANE_Int brx,SANE_Int bry,SANE_Int offset,SANE_Bool half_step,SANE_Byte * regs,Lexmark_Device * dev)2401 low_set_scan_area (SANE_Int res,
2402 SANE_Int tlx,
2403 SANE_Int tly,
2404 SANE_Int brx,
2405 SANE_Int bry,
2406 SANE_Int offset,
2407 SANE_Bool half_step,
2408 SANE_Byte * regs, Lexmark_Device * dev)
2409 {
2410
2411 SANE_Int vert_start = 0;
2412 SANE_Int hor_start = 0;
2413 SANE_Int vert_end;
2414 SANE_Int hor_end;
2415
2416 low_get_start_loc (res, &vert_start, &hor_start, offset, dev);
2417
2418 /* convert pixel height to vertical location coordinates */
2419 vert_end = vert_start + (bry * res) / 600;
2420 vert_start += (tly * res) / 600;
2421
2422 /* scan area size : for A920, 600 color scans are done at 1200 y dpi */
2423 /* this follow what was found in usb logs */
2424 if (half_step)
2425 {
2426 vert_end = vert_end * 2;
2427 vert_start = vert_start * 2;
2428 }
2429
2430 /* set vertical start position registers */
2431 regs[0x60] = LOBYTE (vert_start);
2432 regs[0x61] = HIBYTE (vert_start);
2433 /* set vertical end position registers */
2434 regs[0x62] = LOBYTE (vert_end);
2435 regs[0x63] = HIBYTE (vert_end);
2436
2437 /* convert pixel width to horizontal location coordinates */
2438
2439 hor_end = hor_start + brx;
2440 hor_start += tlx;
2441
2442 regs[0x66] = LOBYTE (hor_start);
2443 regs[0x67] = HIBYTE (hor_start);
2444 /* set horizontal end position registers */
2445 regs[0x6c] = LOBYTE (hor_end);
2446 regs[0x6d] = HIBYTE (hor_end);
2447
2448 /* Debug */
2449 DBG (2, "low_set_scan_area: vert_start: %d (tly=%d)\n", vert_start, tly);
2450 DBG (2, "low_set_scan_area: vert_end: %d\n", vert_end);
2451 DBG (2, "low_set_scan_area: hor_start: %d\n", hor_start);
2452 DBG (2, "low_set_scan_area: hor_end: %d\n", hor_end);
2453
2454 }
2455
2456 SANE_Int
sanei_lexmark_low_find_start_line(Lexmark_Device * dev)2457 sanei_lexmark_low_find_start_line (Lexmark_Device * dev)
2458 {
2459 /*
2460 This function scans forward 59 lines, reading 88 bytes per line from the
2461 middle of the horizontal line: pixel 0xa84 to pixel 0x9d4. It scans with
2462 the following parameters:
2463 dir=fwd
2464 mode=grayscale
2465 h.res=300 dpi
2466 v.res=600 dpi
2467 hor. pixels = (0xa84 - 0x9d4)/2 = 0x58 = 88
2468 vert. pixels = 0x3e - 0x03 = 0x3b = 59
2469 data = 88x59=5192=0x1448
2470
2471 It assumes we are in the start dot, or just before it. We are reading
2472 enough lines at 600dpi to read past the dot. We return the number of
2473 entirely white lines read consecutively, so we know how far past the
2474 dot we are.
2475
2476 To find the number of consecutive white lines we do the following:
2477
2478 Byte swap the order of the bytes in the buffer.
2479
2480 Go through the buffer finding low and high values, which are computed by
2481 comparing to the weighted average:
2482 weighted_average = (lowest value + (highest value - lowest value)/4)
2483 Low bytes are changed to 0xFF (white), higher of equal bytes are changed
2484 to 0x00 (black),so that the buffer only contains white (0xFF) or black
2485 (0x00) values.
2486
2487 Next, we go through the buffer a line (88 bytes) at a time for 59 lines
2488 to read the entire buffer. For each byte in a line we check if the
2489 byte is black. If it is we increment the black byte counter.
2490
2491 After each line we check the black byte counter. If it is greater than 0
2492 we increment the black line count and set the white line count to 0. If
2493 there were no black bytes in the line we set the black line count to 0
2494 and increment the white line count.
2495
2496 When all lines have been processed we return the white line count.
2497 */
2498
2499
2500 int blackLineCount = 0;
2501 int whiteLineCount = 0;
2502 int blackByteCounter = 0;
2503 unsigned char max_byte = 0;
2504 unsigned char min_byte = 0xFF;
2505 unsigned char weighted_average;
2506 int i, j;
2507 #ifdef DEEP_DEBUG
2508 FILE *fdbg = NULL;
2509 #endif
2510
2511 SANE_Byte poll_result[3];
2512 SANE_Byte *buffer;
2513 SANE_Byte temp_byte;
2514
2515 static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 };
2516
2517 static SANE_Byte command5_block[] = { 0x91, 0x00, 0x14, 0x48 };
2518
2519 size_t cmd_size;
2520 SANE_Bool got_line;
2521
2522 DBG (2, "sanei_lexmark_low_find_start_line:\n");
2523
2524
2525 /* set up registers */
2526 switch (dev->model.sensor_type)
2527 {
2528 case X74_SENSOR:
2529 dev->shadow_regs[0x2c] = 0x04;
2530 dev->shadow_regs[0x2d] = 0x46;
2531 dev->shadow_regs[0x34] = 0x05;
2532 dev->shadow_regs[0x35] = 0x05;
2533 dev->shadow_regs[0x36] = 0x0b;
2534 dev->shadow_regs[0x37] = 0x0b;
2535 dev->shadow_regs[0x38] = 0x11;
2536 dev->shadow_regs[0x40] = 0x40;
2537 rts88xx_set_gain (dev->shadow_regs, 6, 6, 6);
2538 break;
2539 case X1100_B2_SENSOR:
2540 dev->shadow_regs[0x2c] = 0x0f;
2541 dev->shadow_regs[0x2d] = 0x51;
2542 dev->shadow_regs[0x34] = 0x0d;
2543 dev->shadow_regs[0x35] = 0x0d;
2544 dev->shadow_regs[0x36] = 0x1d;
2545 dev->shadow_regs[0x37] = 0x1d;
2546 dev->shadow_regs[0x38] = 0x29;
2547 dev->shadow_regs[0x65] = 0x80;
2548 dev->shadow_regs[0x85] = 0x00;
2549 dev->shadow_regs[0x93] = 0x06;
2550 rts88xx_set_gain (dev->shadow_regs, 6, 6, 6);
2551 break;
2552 case X1100_2C_SENSOR:
2553 rts88xx_set_gain (dev->shadow_regs, 10, 10, 10);
2554 dev->shadow_regs[0x28] = 0xf5;
2555 dev->shadow_regs[0x29] = 0xf7;
2556 dev->shadow_regs[0x2a] = 0xf5;
2557 dev->shadow_regs[0x2b] = 0x17;
2558
2559 dev->shadow_regs[0x2c] = 0x0d;
2560 dev->shadow_regs[0x2d] = 0x4f;
2561 dev->shadow_regs[0x31] = 0x01;
2562 dev->shadow_regs[0x34] = 0x11;
2563 dev->shadow_regs[0x35] = 0x11;
2564 dev->shadow_regs[0x36] = 0x21;
2565 dev->shadow_regs[0x37] = 0x21;
2566 dev->shadow_regs[0x38] = 0x31;
2567 dev->shadow_regs[0x72] = 0x35;
2568 dev->shadow_regs[0x74] = 0x4e;
2569 dev->shadow_regs[0x85] = 0x02;
2570 dev->shadow_regs[0x86] = 0x33;
2571 dev->shadow_regs[0x87] = 0x0f;
2572 dev->shadow_regs[0x88] = 0x24;
2573 dev->shadow_regs[0x91] = 0x19;
2574 dev->shadow_regs[0x92] = 0x20;
2575 dev->shadow_regs[0xea] = 0x00;
2576 dev->shadow_regs[0xeb] = 0x00;
2577 break;
2578 case A920_SENSOR:
2579 dev->shadow_regs[0x2c] = 0x0d;
2580 dev->shadow_regs[0x2d] = 0x4f;
2581 dev->shadow_regs[0x34] = 0x11;
2582 dev->shadow_regs[0x35] = 0x11;
2583 dev->shadow_regs[0x36] = 0x21;
2584 dev->shadow_regs[0x37] = 0x21;
2585 dev->shadow_regs[0x38] = 0x31;
2586 dev->shadow_regs[0x85] = 0x05;
2587 dev->shadow_regs[0x88] = 0x44;
2588 dev->shadow_regs[0x92] = 0x85;
2589 dev->shadow_regs[0x93] = 0x0e;
2590 rts88xx_set_gain (dev->shadow_regs, 6, 6, 6);
2591 break;
2592 case X1200_SENSOR:
2593 dev->shadow_regs[0x2c] = 0x01;
2594 dev->shadow_regs[0x2d] = 0x03;
2595 dev->shadow_regs[0x34] = 0x0d;
2596 dev->shadow_regs[0x35] = 0x0d;
2597 dev->shadow_regs[0x36] = 0x1d;
2598 dev->shadow_regs[0x37] = 0x1d;
2599 dev->shadow_regs[0x38] = 0x29;
2600 dev->shadow_regs[0xea] = 0x00;
2601 dev->shadow_regs[0xeb] = 0x00;
2602 dev->shadow_regs[0x40] = 0x80;
2603 dev->shadow_regs[0x50] = 0x00;
2604 dev->shadow_regs[0x81] = 0x00;
2605 dev->shadow_regs[0x82] = 0x00;
2606 dev->shadow_regs[0x85] = 0x00;
2607 dev->shadow_regs[0x86] = 0x00;
2608 dev->shadow_regs[0x87] = 0xff;
2609 dev->shadow_regs[0x88] = 0x02;
2610 dev->shadow_regs[0x92] = 0x00;
2611 rts88xx_set_gain (dev->shadow_regs, 10, 10, 10);
2612 break;
2613 case X1200_USB2_SENSOR:
2614 dev->shadow_regs[0x2c] = 0x01;
2615 dev->shadow_regs[0x2d] = 0x03;
2616 dev->shadow_regs[0x34] = 0x0d;
2617 dev->shadow_regs[0x35] = 0x0d;
2618 dev->shadow_regs[0x36] = 0x1d;
2619 dev->shadow_regs[0x37] = 0x1d;
2620 dev->shadow_regs[0x38] = 0x29;
2621 dev->shadow_regs[0xea] = 0x00;
2622 dev->shadow_regs[0xeb] = 0x00;
2623 rts88xx_set_gain (dev->shadow_regs, 10, 10, 10);
2624 break;
2625 }
2626
2627 /* set offset to a safe value */
2628 rts88xx_set_offset (dev->shadow_regs, 0x80, 0x80, 0x80);
2629 /* set grayscale scan */
2630 dev->shadow_regs[0x2f] = 0x21;
2631 /* set motor resolution divisor */
2632 dev->shadow_regs[0x39] = 0x01;
2633 /* set vertical start/end positions */
2634 dev->shadow_regs[0x60] = 0x03;
2635 dev->shadow_regs[0x61] = 0x00;
2636 dev->shadow_regs[0x62] = 0x3e;
2637 dev->shadow_regs[0x63] = 0x00;
2638 /* set # of head moves per CIS read */
2639 rts88xx_set_scan_frequency (dev->shadow_regs, 1);
2640 /* set horizontal start position */
2641 dev->shadow_regs[0x66] = 0xd4; /* 0xf2 for X1200 */
2642 dev->shadow_regs[0x67] = 0x09;
2643 /* set horizontal end position */
2644 dev->shadow_regs[0x6c] = 0x84; /* 0xa2 for X1200 */
2645 dev->shadow_regs[0x6d] = 0x0a;
2646 /* set horizontal resolution */
2647 dev->shadow_regs[0x79] = 0x40;
2648 dev->shadow_regs[0x7a] = 0x02;
2649 /* set for ? */
2650 /* Motor enable & Coordinate space denominator */
2651 dev->shadow_regs[0xc3] = 0x81;
2652
2653
2654
2655
2656
2657 switch (dev->model.motor_type)
2658 {
2659 case X1100_MOTOR:
2660 case A920_MOTOR:
2661 /* set for ? */
2662 dev->shadow_regs[0xc5] = 0x22;
2663 /* Movement direction & step size */
2664 dev->shadow_regs[0xc6] = 0x09;
2665 /* step size range2 */
2666 dev->shadow_regs[0xc9] = 0x3b;
2667 /* set for ? */
2668 dev->shadow_regs[0xca] = 0x1f;
2669 dev->shadow_regs[0xe0] = 0xf7;
2670 dev->shadow_regs[0xe1] = 0x16;
2671 /* step size range0 */
2672 dev->shadow_regs[0xe2] = 0x87;
2673 /* ? */
2674 dev->shadow_regs[0xe3] = 0x13;
2675 dev->shadow_regs[0xe4] = 0x1b;
2676 dev->shadow_regs[0xe5] = 0x16;
2677 dev->shadow_regs[0xe6] = 0xdc;
2678 dev->shadow_regs[0xe7] = 0x00;
2679 dev->shadow_regs[0xe8] = 0x00;
2680 dev->shadow_regs[0xe9] = 0x1b;
2681 dev->shadow_regs[0xec] = 0x07;
2682 dev->shadow_regs[0xef] = 0x03;
2683 break;
2684 case X74_MOTOR:
2685 dev->shadow_regs[0xc4] = 0x20;
2686 dev->shadow_regs[0xc5] = 0x22;
2687 /* Movement direction & step size */
2688 dev->shadow_regs[0xc6] = 0x0b;
2689
2690 dev->shadow_regs[0xc8] = 0x04;
2691 dev->shadow_regs[0xc9] = 0x39;
2692 dev->shadow_regs[0xca] = 0x1f;
2693
2694 /* bounds of movement range0 */
2695 dev->shadow_regs[0xe0] = 0x2f;
2696 dev->shadow_regs[0xe1] = 0x11;
2697 /* step size range0 */
2698 dev->shadow_regs[0xe2] = 0x9f;
2699 /* ? */
2700 dev->shadow_regs[0xe3] = 0x0f;
2701 /* bounds of movement range1 */
2702 dev->shadow_regs[0xe4] = 0xcb;
2703
2704 dev->shadow_regs[0xe5] = 0x10;
2705 /* step size range1 */
2706 dev->shadow_regs[0xe6] = 0x64;
2707 /* bounds of movement range2 */
2708 dev->shadow_regs[0xe7] = 0x00;
2709 dev->shadow_regs[0xe8] = 0x00;
2710 /* step size range2 */
2711 dev->shadow_regs[0xe9] = 0x32;
2712 /* bounds of movement range3 */
2713 dev->shadow_regs[0xea] = 0x00;
2714 dev->shadow_regs[0xeb] = 0x00;
2715 /* step size range3 */
2716 dev->shadow_regs[0xec] = 0x0c;
2717 /* bounds of movement range4 -only for 75dpi grayscale */
2718 dev->shadow_regs[0xed] = 0x00;
2719 dev->shadow_regs[0xee] = 0x00;
2720 /* step size range4 */
2721 dev->shadow_regs[0xef] = 0x08;
2722 break;
2723 }
2724
2725
2726 /* Stop the scanner */
2727 low_stop_mvmt (dev->devnum);
2728
2729 /* write regs out twice */
2730 dev->shadow_regs[0x32] = 0x00;
2731 low_write_all_regs (dev->devnum, dev->shadow_regs);
2732 dev->shadow_regs[0x32] = 0x40;
2733 low_write_all_regs (dev->devnum, dev->shadow_regs);
2734
2735 /* Start Scan */
2736 rts88xx_commit (dev->devnum, dev->shadow_regs[0x2c]);
2737
2738 /* Poll the available byte count until not 0 */
2739 got_line = SANE_FALSE;
2740 while (!got_line)
2741 {
2742 cmd_size = 4;
2743 low_usb_bulk_write (dev->devnum, command4_block, &cmd_size);
2744 cmd_size = 0x3;
2745 low_usb_bulk_read (dev->devnum, poll_result, &cmd_size);
2746 if (!
2747 (poll_result[0] == 0 && poll_result[1] == 0 && poll_result[2] == 0))
2748 {
2749 /* if result != 00 00 00 we got data */
2750 got_line = SANE_TRUE;
2751 }
2752 #ifdef FAKE_USB
2753 got_line = SANE_TRUE;
2754 #endif
2755 }
2756
2757
2758 /* create buffer for scan data */
2759 buffer = calloc (5192, sizeof (char));
2760 if (buffer == NULL)
2761 {
2762 return -1;
2763 }
2764
2765 /* Tell the scanner to send the data */
2766 /* Write: 91 00 14 48 */
2767 cmd_size = 4;
2768 low_usb_bulk_write (dev->devnum, command5_block, &cmd_size);
2769 /* Read it */
2770 cmd_size = 0x1448;
2771 low_usb_bulk_read (dev->devnum, buffer, &cmd_size);
2772
2773 /* Stop the scanner */
2774 low_stop_mvmt (dev->devnum);
2775
2776
2777 /* Reverse order of bytes in words of buffer */
2778 for (i = 0; i < 5192; i = i + 2)
2779 {
2780 temp_byte = *(buffer + i);
2781 *(buffer + i) = *(buffer + i + 1);
2782 *(buffer + i + 1) = temp_byte;
2783 }
2784
2785 #ifdef DEEP_DEBUG
2786 fdbg = fopen ("find_start.pnm", "wb");
2787 if (fdbg != NULL)
2788 {
2789 fprintf (fdbg, "P5\n%d %d\n255\n", 88, 59);
2790 fwrite (buffer, 5192, 1, fdbg);
2791 fclose (fdbg);
2792 }
2793 #endif
2794
2795 /* Find the max and the min */
2796 for (i = 0; i < 5192; i++)
2797 {
2798 if (*(buffer + i) > max_byte)
2799 max_byte = *(buffer + i);
2800 if (*(buffer + i) < min_byte)
2801 min_byte = *(buffer + i);
2802 }
2803
2804 weighted_average = min_byte + ((max_byte - min_byte) / 4);
2805
2806 /* Set bytes as black (0x00) or white (0xFF) */
2807 for (i = 0; i < 5192; i++)
2808 {
2809 if (*(buffer + i) > weighted_average)
2810 *(buffer + i) = 0xFF;
2811 else
2812 *(buffer + i) = 0x00;
2813 }
2814
2815 #ifdef DEEP_DEBUG
2816 fdbg = fopen ("find_start_after.pnm", "wb");
2817 if (fdbg != NULL)
2818 {
2819 fprintf (fdbg, "P5\n%d %d\n255\n", 88, 59);
2820 fwrite (buffer, 5192, 1, fdbg);
2821 fclose (fdbg);
2822 }
2823 #endif
2824
2825 /* Go through 59 lines */
2826 for (j = 0; j < 59; j++)
2827 {
2828 blackByteCounter = 0;
2829 /* Go through 88 bytes per line */
2830 for (i = 0; i < 88; i++)
2831 {
2832 /* Is byte black? */
2833 if (*(buffer + (j * 88) + i) == 0)
2834 {
2835 blackByteCounter++;
2836 }
2837 } /* end for line */
2838 if (blackByteCounter > 0)
2839 {
2840 /* This was a black line */
2841 blackLineCount++;
2842 whiteLineCount = 0;
2843 }
2844 else
2845 {
2846 /* This is a white line */
2847 whiteLineCount++;
2848 blackLineCount = 0;
2849 }
2850 } /* end for buffer */
2851
2852 free (buffer);
2853 /* Stop the scanner.
2854 This is needed to get the right distance to the scanning area */
2855 if (dev->model.sensor_type == X74_SENSOR)
2856 low_stop_mvmt (dev->devnum);
2857
2858 DBG (2, "sanei_lexmark_low_find_start_line: end.\n");
2859 return whiteLineCount;
2860 }
2861
2862
2863 SANE_Status
sanei_lexmark_low_set_scan_regs(Lexmark_Device * dev,SANE_Int resolution,SANE_Int offset,SANE_Bool calibrated)2864 sanei_lexmark_low_set_scan_regs (Lexmark_Device * dev, SANE_Int resolution,
2865 SANE_Int offset, SANE_Bool calibrated)
2866 {
2867 SANE_Bool isColourScan;
2868
2869 DBG (2, "sanei_lexmark_low_set_scan_regs:\n");
2870
2871 DBG (7, "sanei_lexmark_low_set_scan_regs: resolution=%d DPI\n", resolution);
2872
2873 /* colour mode */
2874 if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0)
2875 isColourScan = SANE_TRUE;
2876 else
2877 isColourScan = SANE_FALSE;
2878
2879 /* set up registers */
2880 switch (dev->model.sensor_type)
2881 {
2882 case X74_SENSOR:
2883 dev->shadow_regs[0x2c] = 0x03;
2884 dev->shadow_regs[0x2d] = 0x45;
2885 break;
2886 case X1100_B2_SENSOR:
2887 dev->shadow_regs[0x2c] = 0x0f;
2888 dev->shadow_regs[0x2d] = 0x51;
2889 break;
2890 case X1100_2C_SENSOR:
2891 dev->shadow_regs[0x2c] = 0x0d;
2892 dev->shadow_regs[0x2d] = 0x4f;
2893 break;
2894 case A920_SENSOR:
2895 dev->shadow_regs[0x2c] = 0x0d;
2896 dev->shadow_regs[0x2d] = 0x4f;
2897 break;
2898 case X1200_SENSOR:
2899 dev->shadow_regs[0x2c] = 0x01;
2900 dev->shadow_regs[0x2d] = 0x03;
2901 break;
2902 case X1200_USB2_SENSOR:
2903 dev->shadow_regs[0x2c] = 0x01;
2904 dev->shadow_regs[0x2d] = 0x03;
2905 break;
2906 }
2907
2908 low_set_scan_area (resolution,
2909 dev->val[OPT_TL_X].w,
2910 dev->val[OPT_TL_Y].w,
2911 dev->val[OPT_BR_X].w,
2912 dev->val[OPT_BR_Y].w,
2913 offset,
2914 (dev->model.motor_type == A920_MOTOR
2915 || dev->model.motor_type == X74_MOTOR) && isColourScan
2916 && (resolution == 600), dev->shadow_regs, dev);
2917
2918 /* may be we could use a sensor descriptor that would held the max horiz dpi */
2919 if (dev->val[OPT_RESOLUTION].w < 600)
2920 dev->shadow_regs[0x7a] = 600 / dev->val[OPT_RESOLUTION].w;
2921 else
2922 dev->shadow_regs[0x7a] = 1;
2923
2924 /* 75dpi x 75dpi */
2925 if (resolution == 75)
2926 {
2927 DBG (5, "sanei_lexmark_low_set_scan_regs(): 75 DPI resolution\n");
2928
2929 if (isColourScan)
2930 {
2931 switch (dev->model.sensor_type)
2932 {
2933 case X74_SENSOR:
2934
2935 dev->shadow_regs[0x34] = 0x04;
2936 dev->shadow_regs[0x36] = 0x03;
2937 dev->shadow_regs[0x38] = 0x03;
2938
2939 dev->shadow_regs[0x79] = 0x08;
2940
2941 dev->shadow_regs[0x80] = 0x0d;
2942 dev->shadow_regs[0x81] = 0x0e;
2943 dev->shadow_regs[0x82] = 0x02;
2944
2945 dev->shadow_regs[0x85] = 0x00;
2946 dev->shadow_regs[0x86] = 0x00;
2947 dev->shadow_regs[0x87] = 0x00;
2948 dev->shadow_regs[0x88] = 0x00;
2949
2950 dev->shadow_regs[0x91] = 0x00;
2951 dev->shadow_regs[0x92] = 0x00;
2952 dev->shadow_regs[0x93] = 0x06;;
2953
2954 break;
2955
2956 case X1100_B2_SENSOR:
2957 dev->shadow_regs[0x34] = 0x05;
2958 dev->shadow_regs[0x36] = 0x05;
2959 dev->shadow_regs[0x38] = 0x05;
2960
2961 dev->shadow_regs[0x80] = 0x0c;
2962 dev->shadow_regs[0x81] = 0x0c;
2963 dev->shadow_regs[0x82] = 0x09;
2964
2965 dev->shadow_regs[0x85] = 0x00;
2966 dev->shadow_regs[0x86] = 0x00;
2967 dev->shadow_regs[0x87] = 0x00;
2968 dev->shadow_regs[0x88] = 0x00;
2969
2970 dev->shadow_regs[0x91] = 0x8c;
2971 dev->shadow_regs[0x92] = 0x40;
2972 dev->shadow_regs[0x93] = 0x06;
2973 break;
2974
2975 case X1100_2C_SENSOR:
2976 dev->shadow_regs[0x34] = 0x03;
2977 dev->shadow_regs[0x36] = 0x04;
2978 dev->shadow_regs[0x38] = 0x03;
2979
2980 dev->shadow_regs[0x80] = 0x00;
2981 dev->shadow_regs[0x81] = 0x02;
2982 dev->shadow_regs[0x82] = 0x03;
2983
2984 dev->shadow_regs[0x85] = 0x20;
2985 dev->shadow_regs[0x86] = 0x00;
2986 dev->shadow_regs[0x87] = 0x00;
2987 dev->shadow_regs[0x88] = 0x00;
2988
2989 dev->shadow_regs[0x91] = 0x00;
2990 dev->shadow_regs[0x92] = 0x00;
2991 dev->shadow_regs[0x93] = 0x06;
2992 break;
2993
2994 case A920_SENSOR:
2995 dev->shadow_regs[0x34] = 0x02;
2996 dev->shadow_regs[0x36] = 0x04;
2997 dev->shadow_regs[0x38] = 0x03;
2998
2999 dev->shadow_regs[0x80] = 0x07;
3000 dev->shadow_regs[0x81] = 0x0f;
3001 dev->shadow_regs[0x82] = 0x03;
3002
3003 dev->shadow_regs[0x85] = 0x05;
3004 dev->shadow_regs[0x86] = 0x14;
3005 dev->shadow_regs[0x87] = 0x06;
3006 dev->shadow_regs[0x88] = 0x44;
3007
3008 dev->shadow_regs[0x91] = 0x60;
3009 dev->shadow_regs[0x92] = 0x85;
3010 dev->shadow_regs[0x93] = 0x0e;
3011 break;
3012
3013 case X1200_SENSOR:
3014 dev->shadow_regs[0x34] = 0x02;
3015 dev->shadow_regs[0x36] = 0x03;
3016 dev->shadow_regs[0x38] = 0x01;
3017
3018 dev->shadow_regs[0x79] = 0x20;
3019
3020 dev->shadow_regs[0x80] = 0x08;
3021 dev->shadow_regs[0x81] = 0x02;
3022 dev->shadow_regs[0x82] = 0x0d;
3023
3024 dev->shadow_regs[0x85] = 0x20;
3025 dev->shadow_regs[0x86] = 0x1e;
3026 dev->shadow_regs[0x87] = 0x39;
3027 dev->shadow_regs[0x88] = 0x00;
3028
3029 dev->shadow_regs[0x91] = 0x00;
3030 /* dev->shadow_regs[0x92] = 0x92; */
3031 dev->shadow_regs[0x93] = 0x06;
3032 break;
3033
3034 case X1200_USB2_SENSOR:
3035 dev->shadow_regs[0x34] = 0x04;
3036 dev->shadow_regs[0x36] = 0x05;
3037 dev->shadow_regs[0x38] = 0x04;
3038
3039 dev->shadow_regs[0x80] = 0x01;
3040 dev->shadow_regs[0x81] = 0x0a;
3041 dev->shadow_regs[0x82] = 0x0b;
3042 break;
3043 }
3044
3045 switch (dev->model.motor_type)
3046 {
3047 case X74_MOTOR:
3048 dev->shadow_regs[0xc2] = 0x80;
3049 /* ? */
3050 dev->shadow_regs[0xc4] = 0x20;
3051 dev->shadow_regs[0xc5] = 0x0c;
3052 dev->shadow_regs[0xc6] = 0x0b;
3053
3054 dev->shadow_regs[0xc8] = 0x04;
3055 dev->shadow_regs[0xc9] = 0x39;
3056 dev->shadow_regs[0xca] = 0x01;
3057
3058 /* bounds of movement range0 */
3059 dev->shadow_regs[0xe0] = 0x1b;
3060 dev->shadow_regs[0xe1] = 0x0a;
3061 /* step size range0 */
3062 dev->shadow_regs[0xe2] = 0x4f;
3063 /* ? */
3064 dev->shadow_regs[0xe3] = 0x01;
3065 /* bounds of movement range1 */
3066 dev->shadow_regs[0xe4] = 0xb3;
3067
3068 dev->shadow_regs[0xe5] = 0x09;
3069 /* step size range1 */
3070 dev->shadow_regs[0xe6] = 0x0d;
3071 /* bounds of movement range2 */
3072 dev->shadow_regs[0xe7] = 0xe5;
3073 dev->shadow_regs[0xe8] = 0x02;
3074 /* step size range2 */
3075 dev->shadow_regs[0xe9] = 0x05;
3076 /* bounds of movement range3 */
3077 dev->shadow_regs[0xea] = 0xa0;
3078 dev->shadow_regs[0xeb] = 0x01;
3079 /* step size range3 */
3080 dev->shadow_regs[0xec] = 0x01;
3081 /* bounds of movement range4 */
3082 dev->shadow_regs[0xed] = 0x00;
3083 dev->shadow_regs[0xee] = 0x00;
3084 /* step size range4 */
3085 dev->shadow_regs[0xef] = 0x01;
3086 break;
3087 case A920_MOTOR:
3088 case X1100_MOTOR:
3089 /* ? */
3090 dev->shadow_regs[0xc5] = 0x0a;
3091 /* bounds of movement range0 */
3092 dev->shadow_regs[0xe0] = 0x2b;
3093 dev->shadow_regs[0xe1] = 0x0a;
3094 /* step size range0 */
3095 dev->shadow_regs[0xe2] = 0x7f;
3096 /* ? */
3097 dev->shadow_regs[0xe3] = 0x01;
3098 /* bounds of movement range1 */
3099 dev->shadow_regs[0xe4] = 0xbb;
3100 dev->shadow_regs[0xe5] = 0x09;
3101 /* step size range1 */
3102 dev->shadow_regs[0xe6] = 0x0e;
3103 /* bounds of movement range2 */
3104 dev->shadow_regs[0xe7] = 0x2b;
3105 dev->shadow_regs[0xe8] = 0x03;
3106 /* step size range2 */
3107 dev->shadow_regs[0xe9] = 0x05;
3108 /* bounds of movement range3 */
3109 dev->shadow_regs[0xea] = 0xa0;
3110 dev->shadow_regs[0xeb] = 0x01;
3111 /* step size range3 */
3112 dev->shadow_regs[0xec] = 0x01;
3113 /* step size range4 */
3114 dev->shadow_regs[0xef] = 0x01;
3115 break;
3116 }
3117
3118 /* set colour scan */
3119 dev->shadow_regs[0x2f] = 0x11;
3120
3121 dev->shadow_regs[0x35] = 0x01;
3122 dev->shadow_regs[0x37] = 0x01;
3123 /* Motor enable & Coordinate space denominator */
3124 dev->shadow_regs[0xc3] = 0x83;
3125 }
3126 else /* 75 dpi gray */
3127 {
3128 switch (dev->model.sensor_type)
3129 {
3130 case X74_SENSOR:
3131
3132 dev->shadow_regs[0x34] = 0x01;
3133 dev->shadow_regs[0x35] = 0x01;
3134 dev->shadow_regs[0x36] = 0x02;
3135 dev->shadow_regs[0x37] = 0x02;
3136 dev->shadow_regs[0x38] = 0x03;
3137 dev->shadow_regs[0x39] = 0x0f;
3138
3139 dev->shadow_regs[0x40] = 0x80;
3140
3141 dev->shadow_regs[0x79] = 0x08;
3142
3143 dev->shadow_regs[0x85] = 0x00;
3144 dev->shadow_regs[0x86] = 0x00;
3145 dev->shadow_regs[0x87] = 0x00;
3146 dev->shadow_regs[0x88] = 0x00;
3147
3148 dev->shadow_regs[0x8c] = 0x02;
3149 dev->shadow_regs[0x8d] = 0x01;
3150 dev->shadow_regs[0x8e] = 0x60;
3151 dev->shadow_regs[0x8f] = 0x80;
3152
3153 dev->shadow_regs[0x91] = 0x00;
3154 dev->shadow_regs[0x92] = 0x00;
3155 dev->shadow_regs[0x93] = 0x06;
3156
3157 break;
3158
3159 case X1100_B2_SENSOR:
3160 dev->shadow_regs[0x34] = 0x02;
3161 dev->shadow_regs[0x35] = 0x02;
3162 dev->shadow_regs[0x36] = 0x04;
3163 dev->shadow_regs[0x37] = 0x04;
3164 dev->shadow_regs[0x38] = 0x06;
3165
3166 dev->shadow_regs[0x85] = 0x20;
3167 dev->shadow_regs[0x86] = 0x00;
3168 dev->shadow_regs[0x87] = 0x00;
3169 dev->shadow_regs[0x88] = 0x00;
3170
3171 dev->shadow_regs[0x91] = 0x00;
3172 dev->shadow_regs[0x92] = 0x00;
3173 dev->shadow_regs[0x93] = 0x06;
3174 break;
3175 case X1100_2C_SENSOR:
3176 dev->shadow_regs[0x34] = 0x01;
3177 dev->shadow_regs[0x35] = 0x01;
3178 dev->shadow_regs[0x36] = 0x02;
3179 dev->shadow_regs[0x37] = 0x02;
3180 dev->shadow_regs[0x38] = 0x03; /* these are half of B2 sensor */
3181
3182 dev->shadow_regs[0x85] = 0x20;
3183 dev->shadow_regs[0x86] = 0x00;
3184 dev->shadow_regs[0x87] = 0x00;
3185 dev->shadow_regs[0x88] = 0x00;
3186
3187 dev->shadow_regs[0x91] = 0x00;
3188 dev->shadow_regs[0x92] = 0x00;
3189 dev->shadow_regs[0x92] = 0x00;
3190 dev->shadow_regs[0x93] = 0x06;
3191 break;
3192 case A920_SENSOR:
3193 dev->shadow_regs[0x34] = 0x01;
3194 dev->shadow_regs[0x35] = 0x01;
3195 dev->shadow_regs[0x36] = 0x02;
3196 dev->shadow_regs[0x37] = 0x02;
3197 dev->shadow_regs[0x38] = 0x03;
3198
3199 dev->shadow_regs[0x85] = 0x0d;
3200 dev->shadow_regs[0x86] = 0x14;
3201 dev->shadow_regs[0x87] = 0x06;
3202 dev->shadow_regs[0x88] = 0x45;
3203
3204 dev->shadow_regs[0x91] = 0x60;
3205 dev->shadow_regs[0x92] = 0x8d;
3206 dev->shadow_regs[0x93] = 0x0e;
3207 break;
3208 case X1200_SENSOR:
3209 dev->shadow_regs[0x34] = 0x01;
3210 dev->shadow_regs[0x35] = 0x01;
3211 dev->shadow_regs[0x36] = 0x02;
3212 dev->shadow_regs[0x37] = 0x02;
3213 dev->shadow_regs[0x38] = 0x02;
3214
3215 dev->shadow_regs[0x79] = 0x20;
3216
3217 dev->shadow_regs[0x85] = 0x00;
3218 dev->shadow_regs[0x86] = 0x00;
3219 dev->shadow_regs[0x87] = 0xff;
3220 dev->shadow_regs[0x88] = 0x02;
3221
3222 dev->shadow_regs[0x92] = 0x00;
3223 break;
3224 case X1200_USB2_SENSOR:
3225 dev->shadow_regs[0x34] = 0x01;
3226 dev->shadow_regs[0x35] = 0x01;
3227 dev->shadow_regs[0x36] = 0x02;
3228 dev->shadow_regs[0x37] = 0x02;
3229 dev->shadow_regs[0x38] = 0x02;
3230
3231 dev->shadow_regs[0x79] = 0x20;
3232
3233 dev->shadow_regs[0x85] = 0x00;
3234 dev->shadow_regs[0x86] = 0x00;
3235 dev->shadow_regs[0x87] = 0xff;
3236 dev->shadow_regs[0x88] = 0x02;
3237
3238 dev->shadow_regs[0x92] = 0x00;
3239 break;
3240 }
3241 switch (dev->model.motor_type)
3242 {
3243 case X74_MOTOR:
3244 /* ? */
3245 dev->shadow_regs[0xc4] = 0x20;
3246 dev->shadow_regs[0xc5] = 0x0a;
3247 dev->shadow_regs[0xc6] = 0x0b;
3248
3249 dev->shadow_regs[0xc8] = 0x04;
3250 dev->shadow_regs[0xc9] = 0x39;
3251 dev->shadow_regs[0xca] = 0x01;
3252
3253 /* bounds of movement range0 */
3254 dev->shadow_regs[0xe0] = 0x07;
3255 dev->shadow_regs[0xe1] = 0x18;
3256 /* step size range0 */
3257 dev->shadow_regs[0xe2] = 0xe7;
3258 /* ? */
3259 dev->shadow_regs[0xe3] = 0x03;
3260 /* bounds of movement range1 */
3261 dev->shadow_regs[0xe4] = 0xe7;
3262 dev->shadow_regs[0xe5] = 0x14;
3263 /* step size range1 */
3264 dev->shadow_regs[0xe6] = 0x64;
3265 /* bounds of movement range2 */
3266 dev->shadow_regs[0xe7] = 0xcb;
3267 dev->shadow_regs[0xe8] = 0x08;
3268 /* step size range2 */
3269 dev->shadow_regs[0xe9] = 0x32;
3270 /* bounds of movement range3 */
3271 dev->shadow_regs[0xea] = 0xe3;
3272 dev->shadow_regs[0xeb] = 0x04;
3273 /* step size range3 */
3274 dev->shadow_regs[0xec] = 0x0c;
3275 /* bounds of movement range4 */
3276 dev->shadow_regs[0xed] = 0x00;
3277 dev->shadow_regs[0xee] = 0x00;
3278 /* step size range4 */
3279 dev->shadow_regs[0xef] = 0x08;
3280 break;
3281 case A920_MOTOR:
3282 case X1100_MOTOR:
3283 /* ? */
3284 dev->shadow_regs[0xc5] = 0x10;
3285 /* Movement direction & step size */
3286 dev->shadow_regs[0xc6] = 0x09;
3287
3288 dev->shadow_regs[0xc9] = 0x3b;
3289 dev->shadow_regs[0xca] = 0x01;
3290 /* bounds of movement range0 */
3291 dev->shadow_regs[0xe0] = 0x4d;
3292 dev->shadow_regs[0xe1] = 0x1c;
3293 /* step size range0 */
3294 dev->shadow_regs[0xe2] = 0x71;
3295 /* ? */
3296 dev->shadow_regs[0xe3] = 0x02;
3297 /* bounds of movement range1 */
3298 dev->shadow_regs[0xe4] = 0x6d;
3299 dev->shadow_regs[0xe5] = 0x15;
3300 /* step size range1 */
3301 dev->shadow_regs[0xe6] = 0xdc;
3302 /* bounds of movement range2 */
3303 dev->shadow_regs[0xe7] = 0xad;
3304 dev->shadow_regs[0xe8] = 0x07;
3305 /* step size range2 */
3306 dev->shadow_regs[0xe9] = 0x1b;
3307 /* bounds of movement range3 */
3308 dev->shadow_regs[0xea] = 0xe1;
3309 dev->shadow_regs[0xeb] = 0x03;
3310 /* step size range3 */
3311 dev->shadow_regs[0xec] = 0x07;
3312 /* bounds of movement range4 -only for 75dpi grayscale */
3313 dev->shadow_regs[0xed] = 0xc2;
3314 dev->shadow_regs[0xee] = 0x02;
3315 /* step size range4 */
3316 dev->shadow_regs[0xef] = 0x03;
3317 break;
3318 }
3319
3320 /* set grayscale scan */
3321 dev->shadow_regs[0x2f] = 0x21;
3322
3323 /* set ? only for colour? */
3324 dev->shadow_regs[0x80] = 0x00;
3325 dev->shadow_regs[0x81] = 0x00;
3326 dev->shadow_regs[0x82] = 0x00;
3327 /* Motor enable & Coordinate space denominator */
3328 dev->shadow_regs[0xc3] = 0x81;
3329
3330 }
3331
3332 /* set motor resolution divisor */
3333 dev->shadow_regs[0x39] = 0x0f;
3334
3335 /* set # of head moves per CIS read */
3336 rts88xx_set_scan_frequency (dev->shadow_regs, 1);
3337
3338 /* set horizontal resolution */
3339 if (dev->model.sensor_type != X1200_SENSOR)
3340 dev->shadow_regs[0x79] = 0x08;
3341
3342 }
3343
3344 /* 150dpi x 150dpi */
3345 if (resolution == 150)
3346 {
3347 DBG (5, "sanei_lexmark_low_set_scan_regs(): 150 DPI resolution\n");
3348
3349 if (isColourScan)
3350 {
3351
3352 switch (dev->model.sensor_type)
3353 {
3354 case X74_SENSOR:
3355 dev->shadow_regs[0x34] = 0x08;
3356 dev->shadow_regs[0x36] = 0x06;
3357 dev->shadow_regs[0x38] = 0x05;
3358 dev->shadow_regs[0x39] = 0x07;
3359
3360 /* resolution divisor */
3361 dev->shadow_regs[0x79] = 0x08;
3362
3363 dev->shadow_regs[0x80] = 0x0a;
3364 dev->shadow_regs[0x81] = 0x0c;
3365 dev->shadow_regs[0x82] = 0x04;
3366
3367 dev->shadow_regs[0x85] = 0x00;
3368 dev->shadow_regs[0x86] = 0x00;
3369 dev->shadow_regs[0x87] = 0x00;
3370 dev->shadow_regs[0x88] = 0x00;
3371
3372 dev->shadow_regs[0x91] = 0x00;
3373 dev->shadow_regs[0x92] = 0x00;
3374 dev->shadow_regs[0x93] = 0x06;
3375 break;
3376 case X1100_B2_SENSOR:
3377 dev->shadow_regs[0x34] = 0x0b;
3378 dev->shadow_regs[0x36] = 0x0b;
3379 dev->shadow_regs[0x38] = 0x0a;
3380
3381 dev->shadow_regs[0x80] = 0x05;
3382 dev->shadow_regs[0x81] = 0x05;
3383 dev->shadow_regs[0x82] = 0x0a;
3384
3385 dev->shadow_regs[0x85] = 0x83;
3386 dev->shadow_regs[0x86] = 0x7e;
3387 dev->shadow_regs[0x87] = 0xad;
3388 dev->shadow_regs[0x88] = 0x35;
3389
3390 dev->shadow_regs[0x91] = 0xfe;
3391 dev->shadow_regs[0x92] = 0xdf;
3392 dev->shadow_regs[0x93] = 0x0e;
3393 break;
3394 case X1100_2C_SENSOR:
3395 dev->shadow_regs[0x34] = 0x05;
3396 dev->shadow_regs[0x36] = 0x07;
3397 dev->shadow_regs[0x38] = 0x05;
3398
3399 dev->shadow_regs[0x80] = 0x00;
3400 dev->shadow_regs[0x81] = 0x02;
3401 dev->shadow_regs[0x82] = 0x06;
3402
3403 dev->shadow_regs[0x85] = 0x20;
3404 dev->shadow_regs[0x86] = 0x00;
3405 dev->shadow_regs[0x87] = 0x00;
3406 dev->shadow_regs[0x88] = 0x00;
3407
3408 dev->shadow_regs[0x91] = 0x00;
3409 dev->shadow_regs[0x92] = 0x00;
3410 dev->shadow_regs[0x93] = 0x06;
3411 break;
3412 case A920_SENSOR:
3413 dev->shadow_regs[0x34] = 0x03;
3414 dev->shadow_regs[0x36] = 0x08;
3415 dev->shadow_regs[0x38] = 0x05;
3416
3417 dev->shadow_regs[0x80] = 0x0e;
3418 dev->shadow_regs[0x81] = 0x07;
3419 dev->shadow_regs[0x82] = 0x02;
3420
3421 dev->shadow_regs[0x85] = 0x05;
3422 dev->shadow_regs[0x86] = 0x14;
3423 dev->shadow_regs[0x87] = 0x06;
3424 dev->shadow_regs[0x88] = 0x04;
3425
3426 dev->shadow_regs[0x91] = 0xe0;
3427 dev->shadow_regs[0x92] = 0x85;
3428 dev->shadow_regs[0x93] = 0x0e;
3429 break;
3430 case X1200_SENSOR:
3431 dev->shadow_regs[0x34] = 0x04;
3432 dev->shadow_regs[0x36] = 0x05;
3433 dev->shadow_regs[0x38] = 0x02;
3434 /* data compression
3435 dev->shadow_regs[0x40] = 0x90;
3436 dev->shadow_regs[0x50] = 0x20; */
3437 /* no data compression */
3438 dev->shadow_regs[0x40] = 0x80;
3439 dev->shadow_regs[0x50] = 0x00;
3440
3441 dev->shadow_regs[0x79] = 0x20;
3442
3443 dev->shadow_regs[0x80] = 0x00;
3444 dev->shadow_regs[0x81] = 0x07;
3445 dev->shadow_regs[0x82] = 0x0b;
3446
3447 dev->shadow_regs[0x85] = 0x20;
3448 dev->shadow_regs[0x86] = 0x1e;
3449 dev->shadow_regs[0x87] = 0x39;
3450 dev->shadow_regs[0x88] = 0x00;
3451
3452 dev->shadow_regs[0x92] = 0x92;
3453
3454 break;
3455 case X1200_USB2_SENSOR:
3456 dev->shadow_regs[0x34] = 0x04;
3457 dev->shadow_regs[0x36] = 0x05;
3458 dev->shadow_regs[0x38] = 0x02;
3459
3460 dev->shadow_regs[0x40] = 0x80;
3461 dev->shadow_regs[0x50] = 0x00;
3462
3463 dev->shadow_regs[0x79] = 0x20;
3464
3465 dev->shadow_regs[0x80] = 0x00;
3466 dev->shadow_regs[0x81] = 0x07;
3467 dev->shadow_regs[0x82] = 0x0b;
3468
3469 dev->shadow_regs[0x85] = 0x20;
3470 dev->shadow_regs[0x86] = 0x1e;
3471 dev->shadow_regs[0x87] = 0x39;
3472 dev->shadow_regs[0x88] = 0x00;
3473
3474 dev->shadow_regs[0x92] = 0x92;
3475 break;
3476 } /* switch */
3477 switch (dev->model.motor_type)
3478 {
3479 case X74_MOTOR:
3480 dev->shadow_regs[0xc2] = 0x80;
3481 /* ? */
3482 dev->shadow_regs[0xc4] = 0x20;
3483
3484 dev->shadow_regs[0xc5] = 0x0e;
3485 /* Movement direction & step size */
3486 dev->shadow_regs[0xc6] = 0x0b;
3487 dev->shadow_regs[0xc7] = 0x00;
3488 dev->shadow_regs[0xc8] = 0x04;
3489 dev->shadow_regs[0xc9] = 0x39;
3490 dev->shadow_regs[0xca] = 0x03;
3491
3492 /* bounds of movement range0 */
3493 dev->shadow_regs[0xe0] = 0x41;
3494 dev->shadow_regs[0xe1] = 0x09;
3495 /* step size range0 */
3496 dev->shadow_regs[0xe2] = 0x89;
3497 /* ? */
3498 dev->shadow_regs[0xe3] = 0x02;
3499 /* bounds of movement range1 */
3500 dev->shadow_regs[0xe4] = 0x0d;
3501
3502 dev->shadow_regs[0xe5] = 0x09;
3503 /* step size range1 */
3504 dev->shadow_regs[0xe6] = 0x0d;
3505 /* bounds of movement range2 */
3506 dev->shadow_regs[0xe7] = 0xe8;
3507 dev->shadow_regs[0xe8] = 0x02;
3508 /* step size range2 */
3509 dev->shadow_regs[0xe9] = 0x05;
3510 /* bounds of movement range3 */
3511 dev->shadow_regs[0xea] = 0x00;
3512 dev->shadow_regs[0xeb] = 0x00;
3513 /* step size range3 */
3514 dev->shadow_regs[0xec] = 0x01;
3515 /* bounds of movement range4 */
3516 dev->shadow_regs[0xed] = 0x00;
3517 dev->shadow_regs[0xee] = 0x00;
3518 /* step size range4 */
3519 dev->shadow_regs[0xef] = 0x01;
3520 break;
3521 case X1100_MOTOR:
3522 case A920_MOTOR:
3523 /* ? */
3524 dev->shadow_regs[0xc5] = 0x0e;
3525 /* ? */
3526 dev->shadow_regs[0xc9] = 0x3a;
3527 dev->shadow_regs[0xca] = 0x03;
3528 /* bounds of movement range0 */
3529 dev->shadow_regs[0xe0] = 0x61;
3530 dev->shadow_regs[0xe1] = 0x0a;
3531 /* step size range0 */
3532 dev->shadow_regs[0xe2] = 0xed;
3533 /* ? */
3534 dev->shadow_regs[0xe3] = 0x02;
3535 /* bounds of movement range1 */
3536 dev->shadow_regs[0xe4] = 0x29;
3537 dev->shadow_regs[0xe5] = 0x0a;
3538 /* step size range1 */
3539 dev->shadow_regs[0xe6] = 0x0e;
3540 /* bounds of movement range2 */
3541 dev->shadow_regs[0xe7] = 0x29;
3542 dev->shadow_regs[0xe8] = 0x03;
3543 /* step size range2 */
3544 dev->shadow_regs[0xe9] = 0x05;
3545 /* bounds of movement range3 */
3546 dev->shadow_regs[0xea] = 0x00;
3547 dev->shadow_regs[0xeb] = 0x00;
3548 /* step size range3 */
3549 dev->shadow_regs[0xec] = 0x01;
3550 /* step size range4 */
3551 dev->shadow_regs[0xef] = 0x01;
3552 break;
3553 }
3554 /* set colour scan */
3555 dev->shadow_regs[0x2f] = 0x11;
3556
3557 dev->shadow_regs[0x35] = 0x01;
3558 dev->shadow_regs[0x37] = 0x01;
3559 /* Motor enable & Coordinate space denominator */
3560 dev->shadow_regs[0xc3] = 0x83;
3561
3562 } /* if (isColourScan) */
3563 else
3564 {
3565 switch (dev->model.sensor_type)
3566 {
3567 case X74_SENSOR:
3568
3569 dev->shadow_regs[0x34] = 0x02;
3570 dev->shadow_regs[0x35] = 0x02;
3571 dev->shadow_regs[0x36] = 0x04;
3572 dev->shadow_regs[0x37] = 0x04;
3573 dev->shadow_regs[0x38] = 0x06;
3574 dev->shadow_regs[0x39] = 0x07;
3575 /* Motor enable & Coordinate space denominator */
3576 dev->shadow_regs[0x40] = 0x40;
3577
3578 /* resolution divisor */
3579 dev->shadow_regs[0x79] = 0x08;
3580
3581 dev->shadow_regs[0x85] = 0x00;
3582 dev->shadow_regs[0x86] = 0x00;
3583 dev->shadow_regs[0x87] = 0x00;
3584 dev->shadow_regs[0x88] = 0x00;
3585
3586 dev->shadow_regs[0x91] = 0x00;
3587 dev->shadow_regs[0x92] = 0x00;
3588 dev->shadow_regs[0x93] = 0x06;
3589 break;
3590 case X1100_B2_SENSOR:
3591 dev->shadow_regs[0x34] = 0x04;
3592 dev->shadow_regs[0x35] = 0x04;
3593 dev->shadow_regs[0x36] = 0x07;
3594 dev->shadow_regs[0x37] = 0x07;
3595 dev->shadow_regs[0x38] = 0x0a;
3596
3597
3598 dev->shadow_regs[0x85] = 0x00;
3599 dev->shadow_regs[0x86] = 0x00;
3600 dev->shadow_regs[0x87] = 0x00;
3601 dev->shadow_regs[0x88] = 0x00;
3602
3603 dev->shadow_regs[0x91] = 0x00;
3604 dev->shadow_regs[0x92] = 0x00;
3605 dev->shadow_regs[0x93] = 0x06;
3606 break;
3607 case X1100_2C_SENSOR:
3608 dev->shadow_regs[0x34] = 0x02;
3609 dev->shadow_regs[0x35] = 0x02;
3610 dev->shadow_regs[0x36] = 0x04;
3611 dev->shadow_regs[0x37] = 0x04;
3612 dev->shadow_regs[0x38] = 0x05;
3613
3614 dev->shadow_regs[0x85] = 0x20;
3615 dev->shadow_regs[0x86] = 0x00;
3616 dev->shadow_regs[0x87] = 0x00;
3617 dev->shadow_regs[0x88] = 0x00;
3618
3619 dev->shadow_regs[0x91] = 0x00;
3620 dev->shadow_regs[0x92] = 0x00;
3621 dev->shadow_regs[0x93] = 0x06;
3622 break;
3623 case A920_SENSOR:
3624 dev->shadow_regs[0x34] = 0x02;
3625 dev->shadow_regs[0x35] = 0x02;
3626 dev->shadow_regs[0x36] = 0x04;
3627 dev->shadow_regs[0x37] = 0x04;
3628 dev->shadow_regs[0x38] = 0x05;
3629
3630 dev->shadow_regs[0x85] = 0x0d;
3631 dev->shadow_regs[0x86] = 0x14;
3632 dev->shadow_regs[0x87] = 0x06;
3633 dev->shadow_regs[0x88] = 0x45;
3634
3635 dev->shadow_regs[0x91] = 0x60;
3636 dev->shadow_regs[0x92] = 0x8d;
3637 dev->shadow_regs[0x93] = 0x0e;
3638 break;
3639 case X1200_SENSOR:
3640 dev->shadow_regs[0x34] = 0x01;
3641 dev->shadow_regs[0x35] = 0x01;
3642 dev->shadow_regs[0x36] = 0x02;
3643 dev->shadow_regs[0x37] = 0x02;
3644 dev->shadow_regs[0x38] = 0x03;
3645
3646 /* dev->shadow_regs[0x40] = 0x90;
3647 dev->shadow_regs[0x50] = 0x20; */
3648 /* no data compression */
3649 dev->shadow_regs[0x40] = 0x80;
3650 dev->shadow_regs[0x50] = 0x00;
3651
3652 dev->shadow_regs[0x79] = 0x20;
3653
3654 dev->shadow_regs[0x85] = 0x00;
3655 dev->shadow_regs[0x86] = 0x00;
3656 dev->shadow_regs[0x87] = 0xff;
3657 dev->shadow_regs[0x88] = 0x02;
3658
3659 dev->shadow_regs[0x92] = 0x92;
3660 break;
3661 case X1200_USB2_SENSOR:
3662 dev->shadow_regs[0x34] = 0x01;
3663 dev->shadow_regs[0x35] = 0x01;
3664 dev->shadow_regs[0x36] = 0x02;
3665 dev->shadow_regs[0x37] = 0x02;
3666 dev->shadow_regs[0x38] = 0x03;
3667
3668 dev->shadow_regs[0x40] = 0x80;
3669 dev->shadow_regs[0x50] = 0x00;
3670
3671 dev->shadow_regs[0x79] = 0x20;
3672
3673 dev->shadow_regs[0x85] = 0x00;
3674 dev->shadow_regs[0x86] = 0x00;
3675 dev->shadow_regs[0x87] = 0xff;
3676 dev->shadow_regs[0x88] = 0x02;
3677
3678 dev->shadow_regs[0x92] = 0x92;
3679 break;
3680 } /* switch */
3681 switch (dev->model.motor_type)
3682 {
3683 case X74_MOTOR:
3684 /* ? */
3685 dev->shadow_regs[0xc4] = 0x20;
3686 dev->shadow_regs[0xc5] = 0x14;
3687 /* Movement direction & step size */
3688 dev->shadow_regs[0xc6] = 0x0b;
3689
3690 dev->shadow_regs[0xc8] = 0x04;
3691 dev->shadow_regs[0xc9] = 0x39;
3692 dev->shadow_regs[0xca] = 0x01;
3693
3694 /* bounds of movement range0 */
3695 dev->shadow_regs[0xe0] = 0x09;
3696 dev->shadow_regs[0xe1] = 0x18;
3697 /* step size range0 */
3698 dev->shadow_regs[0xe2] = 0xe9;
3699 /* ? */
3700 dev->shadow_regs[0xe3] = 0x03;
3701 /* bounds of movement range1 */
3702 dev->shadow_regs[0xe4] = 0x79;
3703
3704 dev->shadow_regs[0xe5] = 0x16;
3705 /* step size range1 */
3706 dev->shadow_regs[0xe6] = 0x64;
3707 /* bounds of movement range2 */
3708 dev->shadow_regs[0xe7] = 0xcd;
3709 dev->shadow_regs[0xe8] = 0x08;
3710 /* step size range2 */
3711 dev->shadow_regs[0xe9] = 0x32;
3712 /* bounds of movement range3 */
3713 dev->shadow_regs[0xea] = 0xe5;
3714 dev->shadow_regs[0xeb] = 0x04;
3715 /* step size range3 */
3716 dev->shadow_regs[0xec] = 0x0c;
3717 /* bounds of movement range4 */
3718 dev->shadow_regs[0xed] = 0x00;
3719 dev->shadow_regs[0xee] = 0x00;
3720 /* step size range4 */
3721 dev->shadow_regs[0xef] = 0x08;
3722 break;
3723 case X1100_MOTOR:
3724 case A920_MOTOR:
3725 /* ? */
3726 dev->shadow_regs[0xc5] = 0x16;
3727 /* Movement direction & step size */
3728 dev->shadow_regs[0xc6] = 0x09;
3729 /* ? */
3730 dev->shadow_regs[0xc9] = 0x3b;
3731 dev->shadow_regs[0xca] = 0x01;
3732 /* bounds of movement range0 */
3733 dev->shadow_regs[0xe0] = 0xdd;
3734 dev->shadow_regs[0xe1] = 0x18;
3735 /* step size range0 */
3736 dev->shadow_regs[0xe2] = 0x01;
3737 /* ? */
3738 dev->shadow_regs[0xe3] = 0x03;
3739 /* bounds of movement range1 */
3740 dev->shadow_regs[0xe4] = 0x6d;
3741 dev->shadow_regs[0xe5] = 0x15;
3742 /* step size range1 */
3743 dev->shadow_regs[0xe6] = 0xdc;
3744 /* bounds of movement range2 */
3745 dev->shadow_regs[0xe7] = 0xad;
3746 dev->shadow_regs[0xe8] = 0x07;
3747 /* step size range2 */
3748 dev->shadow_regs[0xe9] = 0x1b;
3749 /* bounds of movement range3 */
3750 dev->shadow_regs[0xea] = 0xe1;
3751 dev->shadow_regs[0xeb] = 0x03;
3752 /* step size range3 */
3753 dev->shadow_regs[0xec] = 0x07;
3754 /* step size range4 */
3755 dev->shadow_regs[0xef] = 0x03;
3756 break;
3757 }
3758
3759 /* set grayscale scan */
3760 dev->shadow_regs[0x2f] = 0x21;
3761 /* set motor resolution divisor */
3762 dev->shadow_regs[0x39] = 0x07;
3763 /* set ? only for colour? */
3764 dev->shadow_regs[0x80] = 0x00;
3765 dev->shadow_regs[0x81] = 0x00;
3766 dev->shadow_regs[0x82] = 0x00;
3767
3768 /* Motor enable & Coordinate space denominator */
3769 dev->shadow_regs[0xc3] = 0x81;
3770 } /* else (greyscale) */
3771
3772
3773
3774
3775 /* set # of head moves per CIS read */
3776 rts88xx_set_scan_frequency (dev->shadow_regs, 1);
3777
3778 /* hum, horizontal resolution different for X1200 ? */
3779 /* if (dev->model.sensor_type != X1200_SENSOR)
3780 dev->shadow_regs[0x79] = 0x20; */
3781
3782 }
3783
3784 /*300dpi x 300dpi */
3785 if (resolution == 300)
3786 {
3787 DBG (5, "sanei_lexmark_low_set_scan_regs(): 300 DPI resolution\n");
3788
3789 if (isColourScan)
3790 {
3791
3792 switch (dev->model.sensor_type)
3793 {
3794 case X74_SENSOR:
3795 dev->shadow_regs[0x34] = 0x08;
3796 dev->shadow_regs[0x36] = 0x06;
3797 dev->shadow_regs[0x38] = 0x05;
3798 dev->shadow_regs[0x39] = 0x07;
3799
3800 dev->shadow_regs[0x80] = 0x08;
3801 dev->shadow_regs[0x81] = 0x0a;
3802 dev->shadow_regs[0x82] = 0x03;
3803
3804 dev->shadow_regs[0x85] = 0x00;
3805 dev->shadow_regs[0x86] = 0x00;
3806 dev->shadow_regs[0x87] = 0x00;
3807 dev->shadow_regs[0x88] = 0x00;
3808
3809 dev->shadow_regs[0x91] = 0x00;
3810 dev->shadow_regs[0x92] = 0x00;
3811 dev->shadow_regs[0x93] = 0x06;
3812 break;
3813 case X1100_B2_SENSOR:
3814 dev->shadow_regs[0x34] = 0x15;
3815 dev->shadow_regs[0x36] = 0x15;
3816 dev->shadow_regs[0x38] = 0x14;
3817 /* set motor resolution divisor */
3818 dev->shadow_regs[0x39] = 0x03;
3819
3820 dev->shadow_regs[0x80] = 0x0a;
3821 dev->shadow_regs[0x81] = 0x0a;
3822 dev->shadow_regs[0x82] = 0x06;
3823
3824 dev->shadow_regs[0x85] = 0x83;
3825 dev->shadow_regs[0x86] = 0x7e;
3826 dev->shadow_regs[0x87] = 0xad;
3827 dev->shadow_regs[0x88] = 0x35;
3828
3829 dev->shadow_regs[0x91] = 0xfe;
3830 dev->shadow_regs[0x92] = 0xdf;
3831 dev->shadow_regs[0x93] = 0x0e;
3832 break;
3833 case X1100_2C_SENSOR:
3834 dev->shadow_regs[0x34] = 0x08;
3835 dev->shadow_regs[0x36] = 0x0d;
3836 dev->shadow_regs[0x38] = 0x09;
3837 /* set motor resolution divisor */
3838 dev->shadow_regs[0x39] = 0x03;
3839
3840 dev->shadow_regs[0x80] = 0x0e;
3841 dev->shadow_regs[0x81] = 0x04;
3842 dev->shadow_regs[0x82] = 0x0a;
3843
3844 dev->shadow_regs[0x85] = 0x20;
3845 dev->shadow_regs[0x86] = 0x00;
3846 dev->shadow_regs[0x87] = 0x00;
3847 dev->shadow_regs[0x88] = 0x00;
3848
3849 dev->shadow_regs[0x91] = 0x00;
3850 dev->shadow_regs[0x92] = 0x00;
3851 dev->shadow_regs[0x93] = 0x06;
3852 break;
3853 case A920_SENSOR:
3854 dev->shadow_regs[0x34] = 0x06;
3855 dev->shadow_regs[0x36] = 0x10;
3856 dev->shadow_regs[0x38] = 0x09;
3857 /* set motor resolution divisor */
3858 dev->shadow_regs[0x39] = 0x03;
3859
3860 dev->shadow_regs[0x80] = 0x0c;
3861 dev->shadow_regs[0x81] = 0x02;
3862 dev->shadow_regs[0x82] = 0x04;
3863
3864 dev->shadow_regs[0x85] = 0x05;
3865 dev->shadow_regs[0x86] = 0x14;
3866 dev->shadow_regs[0x87] = 0x06;
3867 dev->shadow_regs[0x88] = 0x04;
3868
3869 dev->shadow_regs[0x91] = 0xe0;
3870 dev->shadow_regs[0x92] = 0x85;
3871 dev->shadow_regs[0x93] = 0x0e;
3872 break;
3873 case X1200_SENSOR:
3874 dev->shadow_regs[0x34] = 0x07;
3875 dev->shadow_regs[0x36] = 0x09;
3876 dev->shadow_regs[0x38] = 0x04;
3877 /* set motor resolution divisor */
3878 dev->shadow_regs[0x39] = 0x03;
3879
3880 /* data compression
3881 dev->shadow_regs[0x40] = 0x90;
3882 dev->shadow_regs[0x50] = 0x20; */
3883 /* no data compression */
3884 dev->shadow_regs[0x40] = 0x80;
3885 dev->shadow_regs[0x50] = 0x00;
3886
3887 dev->shadow_regs[0x80] = 0x00;
3888 dev->shadow_regs[0x81] = 0x0e;
3889 dev->shadow_regs[0x82] = 0x06;
3890 break;
3891 case X1200_USB2_SENSOR:
3892 dev->shadow_regs[0x34] = 0x07;
3893 dev->shadow_regs[0x36] = 0x09;
3894 dev->shadow_regs[0x38] = 0x04;
3895 /* set motor resolution divisor */
3896 dev->shadow_regs[0x39] = 0x03;
3897
3898 dev->shadow_regs[0x40] = 0x80;
3899 dev->shadow_regs[0x50] = 0x00;
3900
3901 dev->shadow_regs[0x80] = 0x00;
3902 dev->shadow_regs[0x81] = 0x0e;
3903 dev->shadow_regs[0x82] = 0x06;
3904 break;
3905 }
3906 switch (dev->model.motor_type)
3907 {
3908 case X74_MOTOR:
3909 /* ? */
3910 dev->shadow_regs[0xc4] = 0x20;
3911 dev->shadow_regs[0xc5] = 0x12;
3912 /* Movement direction & step size */
3913 dev->shadow_regs[0xc6] = 0x09;
3914
3915 dev->shadow_regs[0xc8] = 0x04;
3916 dev->shadow_regs[0xc9] = 0x39;
3917 dev->shadow_regs[0xca] = 0x0f;
3918
3919 /* bounds of movement range0 */
3920 dev->shadow_regs[0xe0] = 0x5d;
3921 dev->shadow_regs[0xe1] = 0x05;
3922 /* step size range0 */
3923 dev->shadow_regs[0xe2] = 0xed;
3924 /* ? */
3925 dev->shadow_regs[0xe3] = 0x02;
3926 /* bounds of movement range1 */
3927 dev->shadow_regs[0xe4] = 0x29;
3928 dev->shadow_regs[0xe5] = 0x05;
3929 /* step size range1 */
3930 dev->shadow_regs[0xe6] = 0x0d;
3931 /* bounds of movement range2 */
3932 dev->shadow_regs[0xe7] = 0x00;
3933 dev->shadow_regs[0xe8] = 0x00;
3934 /* step size range2 */
3935 dev->shadow_regs[0xe9] = 0x05;
3936 /* bounds of movement range3 */
3937 dev->shadow_regs[0xea] = 0x00;
3938 dev->shadow_regs[0xeb] = 0x00;
3939 /* step size range3 */
3940 dev->shadow_regs[0xec] = 0x01;
3941 /* bounds of movement range4 -only for 75dpi grayscale */
3942 dev->shadow_regs[0xed] = 0x00;
3943 dev->shadow_regs[0xee] = 0x00;
3944 /* step size range4 */
3945 dev->shadow_regs[0xef] = 0x01;
3946 break;
3947 case A920_MOTOR:
3948 case X1100_MOTOR:
3949 /* ? */
3950 dev->shadow_regs[0xc5] = 0x17;
3951 /* Movement direction & step size */
3952 dev->shadow_regs[0xc6] = 0x09;
3953 /* ? */
3954 dev->shadow_regs[0xc9] = 0x3a;
3955 dev->shadow_regs[0xca] = 0x0a;
3956 /* bounds of movement range0 */
3957 dev->shadow_regs[0xe0] = 0x75;
3958 dev->shadow_regs[0xe1] = 0x0a;
3959 /* step size range0 */
3960 dev->shadow_regs[0xe2] = 0xdd;
3961 /* ? */
3962 dev->shadow_regs[0xe3] = 0x05;
3963 /* bounds of movement range1 */
3964 dev->shadow_regs[0xe4] = 0x59;
3965 dev->shadow_regs[0xe5] = 0x0a;
3966 /* step size range1 */
3967 dev->shadow_regs[0xe6] = 0x0e;
3968 /* bounds of movement range2 */
3969 dev->shadow_regs[0xe7] = 0x00;
3970 dev->shadow_regs[0xe8] = 0x00;
3971 /* step size range2 */
3972 dev->shadow_regs[0xe9] = 0x05;
3973 /* bounds of movement range3 */
3974 dev->shadow_regs[0xea] = 0x00;
3975 dev->shadow_regs[0xeb] = 0x00;
3976 /* step size range3 */
3977 dev->shadow_regs[0xec] = 0x01;
3978 /* step size range4 */
3979 dev->shadow_regs[0xef] = 0x01;
3980 break;
3981 }
3982
3983 dev->shadow_regs[0x35] = 0x01;
3984 dev->shadow_regs[0x37] = 0x01;
3985
3986 /* set colour scan */
3987 dev->shadow_regs[0x2f] = 0x11;
3988
3989 /* Motor enable & Coordinate space denominator */
3990 dev->shadow_regs[0xc3] = 0x83;
3991
3992 }
3993 else /* greyscale */
3994 {
3995
3996 switch (dev->model.sensor_type)
3997 {
3998 case X74_SENSOR:
3999 dev->shadow_regs[0x34] = 0x04;
4000 dev->shadow_regs[0x35] = 0x04;
4001 dev->shadow_regs[0x36] = 0x08;
4002 dev->shadow_regs[0x37] = 0x08;
4003 dev->shadow_regs[0x38] = 0x0c;
4004
4005 dev->shadow_regs[0x85] = 0x00;
4006 dev->shadow_regs[0x86] = 0x00;
4007 dev->shadow_regs[0x87] = 0x00;
4008 dev->shadow_regs[0x88] = 0x00;
4009
4010 dev->shadow_regs[0x91] = 0x00;
4011 dev->shadow_regs[0x92] = 0x00;
4012 dev->shadow_regs[0x93] = 0x06;
4013 break;
4014 case X1100_B2_SENSOR:
4015 dev->shadow_regs[0x34] = 0x08;
4016 dev->shadow_regs[0x35] = 0x08;
4017 dev->shadow_regs[0x36] = 0x0f;
4018 dev->shadow_regs[0x37] = 0x0f;
4019 dev->shadow_regs[0x38] = 0x16;
4020
4021 dev->shadow_regs[0x85] = 0x00;
4022 dev->shadow_regs[0x86] = 0x00;
4023 dev->shadow_regs[0x87] = 0x00;
4024 dev->shadow_regs[0x88] = 0x00;
4025
4026 dev->shadow_regs[0x91] = 0x00;
4027 dev->shadow_regs[0x92] = 0x00;
4028 dev->shadow_regs[0x93] = 0x06;
4029 break;
4030 case X1100_2C_SENSOR:
4031 dev->shadow_regs[0x34] = 0x04;
4032 dev->shadow_regs[0x35] = 0x04;
4033 dev->shadow_regs[0x36] = 0x07;
4034 dev->shadow_regs[0x37] = 0x07;
4035 dev->shadow_regs[0x38] = 0x0a;
4036
4037 dev->shadow_regs[0x85] = 0x20;
4038 dev->shadow_regs[0x86] = 0x00;
4039 dev->shadow_regs[0x87] = 0x00;
4040 dev->shadow_regs[0x88] = 0x00;
4041
4042 dev->shadow_regs[0x91] = 0x00;
4043 dev->shadow_regs[0x92] = 0x00;
4044 dev->shadow_regs[0x93] = 0x06;
4045 break;
4046 case A920_SENSOR:
4047 dev->shadow_regs[0x34] = 0x03;
4048 dev->shadow_regs[0x35] = 0x03;
4049 dev->shadow_regs[0x36] = 0x06;
4050 dev->shadow_regs[0x37] = 0x06;
4051 dev->shadow_regs[0x38] = 0x09;
4052
4053 dev->shadow_regs[0x85] = 0x05;
4054 dev->shadow_regs[0x86] = 0x14;
4055 dev->shadow_regs[0x87] = 0x06;
4056 dev->shadow_regs[0x88] = 0x04;
4057
4058 dev->shadow_regs[0x91] = 0xe0;
4059 dev->shadow_regs[0x92] = 0x85;
4060 dev->shadow_regs[0x93] = 0x0e;
4061 break;
4062 case X1200_SENSOR:
4063 dev->shadow_regs[0x34] = 0x02;
4064 dev->shadow_regs[0x35] = 0x02;
4065 dev->shadow_regs[0x36] = 0x04;
4066 dev->shadow_regs[0x37] = 0x04;
4067 dev->shadow_regs[0x38] = 0x06;
4068 break;
4069 case X1200_USB2_SENSOR:
4070 dev->shadow_regs[0x34] = 0x02;
4071 dev->shadow_regs[0x35] = 0x02;
4072 dev->shadow_regs[0x36] = 0x04;
4073 dev->shadow_regs[0x37] = 0x04;
4074 dev->shadow_regs[0x38] = 0x06;
4075 break;
4076 }
4077 switch (dev->model.motor_type)
4078 {
4079 case X74_MOTOR:
4080 /* ? */
4081 dev->shadow_regs[0xc4] = 0x20;
4082 dev->shadow_regs[0xc5] = 0x1c;
4083 /* Movement direction & step size */
4084 dev->shadow_regs[0xc6] = 0x0b;
4085
4086 dev->shadow_regs[0xc8] = 0x04;
4087 dev->shadow_regs[0xc9] = 0x39;
4088 dev->shadow_regs[0xca] = 0x05;
4089
4090 /* bounds of movement range0 */
4091 dev->shadow_regs[0xe0] = 0x29;
4092 dev->shadow_regs[0xe1] = 0x17;
4093 /* step size range0 */
4094 dev->shadow_regs[0xe2] = 0x8f;
4095 /* ? */
4096 dev->shadow_regs[0xe3] = 0x06;
4097 /* bounds of movement range1 */
4098 dev->shadow_regs[0xe4] = 0x61;
4099
4100 dev->shadow_regs[0xe5] = 0x16;
4101 /* step size range1 */
4102 dev->shadow_regs[0xe6] = 0x64;
4103 /* bounds of movement range2 */
4104 dev->shadow_regs[0xe7] = 0xb5;
4105 dev->shadow_regs[0xe8] = 0x08;
4106 /* step size range2 */
4107 dev->shadow_regs[0xe9] = 0x32;
4108 /* bounds of movement range3 */
4109 dev->shadow_regs[0xea] = 0x00;
4110 dev->shadow_regs[0xeb] = 0x00;
4111 /* step size range3 */
4112 dev->shadow_regs[0xec] = 0x0c;
4113 /* bounds of movement range4 -only for 75dpi grayscale */
4114 dev->shadow_regs[0xed] = 0x00;
4115 dev->shadow_regs[0xee] = 0x00;
4116 /* step size range4 */
4117 dev->shadow_regs[0xef] = 0x08;
4118 break;
4119 case A920_MOTOR:
4120 case X1100_MOTOR:
4121 /* ? */
4122 dev->shadow_regs[0xc5] = 0x19;
4123 /* Movement direction & step size */
4124 dev->shadow_regs[0xc6] = 0x09;
4125 /* ? */
4126 dev->shadow_regs[0xc9] = 0x3a;
4127 dev->shadow_regs[0xca] = 0x08;
4128 /* bounds of movement range0 */
4129 dev->shadow_regs[0xe0] = 0xe3;
4130 dev->shadow_regs[0xe1] = 0x18;
4131 /* step size range0 */
4132 dev->shadow_regs[0xe2] = 0x03;
4133 /* ? */
4134 dev->shadow_regs[0xe3] = 0x06;
4135 /* bounds of movement range1 */
4136 dev->shadow_regs[0xe4] = 0x2b;
4137 dev->shadow_regs[0xe5] = 0x17;
4138 /* step size range1 */
4139 dev->shadow_regs[0xe6] = 0xdc;
4140 /* bounds of movement range2 */
4141 dev->shadow_regs[0xe7] = 0xb3;
4142 dev->shadow_regs[0xe8] = 0x07;
4143 /* step size range2 */
4144 dev->shadow_regs[0xe9] = 0x1b;
4145 /* bounds of movement range3 */
4146 dev->shadow_regs[0xea] = 0x00;
4147 dev->shadow_regs[0xeb] = 0x00;
4148 /* step size range3 */
4149 dev->shadow_regs[0xec] = 0x07;
4150 /* step size range4 */
4151 dev->shadow_regs[0xef] = 0x03;
4152 break;
4153 } /* switch motortype */
4154 /* set grayscale scan */
4155 dev->shadow_regs[0x2f] = 0x21;
4156 /* set motor resolution divisor */
4157 dev->shadow_regs[0x39] = 0x03;
4158
4159 /* set ? only for colour? */
4160 dev->shadow_regs[0x80] = 0x00;
4161 dev->shadow_regs[0x81] = 0x00;
4162 dev->shadow_regs[0x82] = 0x00;
4163 /* Motor enable & Coordinate space denominator */
4164 dev->shadow_regs[0xc3] = 0x81;
4165
4166
4167 } /* else (gray) */
4168
4169 /* set # of head moves per CIS read */
4170 rts88xx_set_scan_frequency (dev->shadow_regs, 1);
4171 /* set horizontal resolution */
4172 dev->shadow_regs[0x79] = 0x20;
4173 }
4174
4175 /* 600dpi x 600dpi */
4176 if (resolution == 600)
4177 {
4178 DBG (5, "sanei_lexmark_low_set_scan_regs(): 600 DPI resolution\n");
4179
4180
4181
4182 if (isColourScan)
4183 {
4184 /* 600 dpi color doesn't work for X74 yet */
4185 if (dev->model.sensor_type == X74_SENSOR)
4186 return SANE_STATUS_INVAL;
4187
4188 switch (dev->model.sensor_type)
4189 {
4190 case X74_SENSOR:
4191 dev->shadow_regs[0x34] = 0x10;
4192 dev->shadow_regs[0x35] = 0x01;
4193 dev->shadow_regs[0x36] = 0x0c;
4194 dev->shadow_regs[0x37] = 0x01;
4195 dev->shadow_regs[0x38] = 0x09;
4196
4197 dev->shadow_regs[0x80] = 0x02;
4198 dev->shadow_regs[0x81] = 0x08;
4199 dev->shadow_regs[0x82] = 0x08;
4200
4201
4202 dev->shadow_regs[0x85] = 0x00;
4203 dev->shadow_regs[0x86] = 0x00;
4204 dev->shadow_regs[0x87] = 0x00;
4205 dev->shadow_regs[0x88] = 0x00;
4206
4207 dev->shadow_regs[0x91] = 0x00;
4208 dev->shadow_regs[0x92] = 0x00;
4209 dev->shadow_regs[0x93] = 0x06;
4210 break;
4211
4212 /*dev->shadow_regs[0x34] = 0x08;
4213 dev->shadow_regs[0x35] = 0x01;
4214 dev->shadow_regs[0x36] = 0x06;
4215 dev->shadow_regs[0x37] = 0x01;
4216 dev->shadow_regs[0x38] = 0x05;
4217
4218
4219 dev->shadow_regs[0x80] = 0x09;
4220 dev->shadow_regs[0x81] = 0x0c;
4221 dev->shadow_regs[0x82] = 0x04;
4222
4223
4224 dev->shadow_regs[0x85] = 0x00;
4225 dev->shadow_regs[0x86] = 0x00;
4226 dev->shadow_regs[0x87] = 0x00;
4227 dev->shadow_regs[0x88] = 0x00;
4228
4229 dev->shadow_regs[0x91] = 0x00;
4230 dev->shadow_regs[0x92] = 0x00;
4231 dev->shadow_regs[0x93] = 0x06;
4232 break; */
4233
4234
4235
4236 case X1100_B2_SENSOR:
4237 dev->shadow_regs[0x34] = 0x15;
4238 dev->shadow_regs[0x36] = 0x15;
4239 dev->shadow_regs[0x38] = 0x14;
4240
4241 dev->shadow_regs[0x80] = 0x02;
4242 dev->shadow_regs[0x81] = 0x02;
4243 dev->shadow_regs[0x82] = 0x08;
4244
4245 dev->shadow_regs[0x85] = 0x83;
4246 dev->shadow_regs[0x86] = 0x7e;
4247 dev->shadow_regs[0x87] = 0xad;
4248 dev->shadow_regs[0x88] = 0x35;
4249
4250 dev->shadow_regs[0x91] = 0xfe;
4251 dev->shadow_regs[0x92] = 0xdf;
4252 dev->shadow_regs[0x93] = 0x0e;
4253 break;
4254 case X1100_2C_SENSOR:
4255 dev->shadow_regs[0x34] = 0x08;
4256 dev->shadow_regs[0x36] = 0x0d;
4257 dev->shadow_regs[0x38] = 0x09;
4258
4259 dev->shadow_regs[0x80] = 0x0e;
4260 dev->shadow_regs[0x81] = 0x02;
4261 dev->shadow_regs[0x82] = 0x0a;
4262
4263 dev->shadow_regs[0x85] = 0x20;
4264 dev->shadow_regs[0x86] = 0x00;
4265 dev->shadow_regs[0x87] = 0x00;
4266 dev->shadow_regs[0x88] = 0x00;
4267
4268 dev->shadow_regs[0x91] = 0x00;
4269 dev->shadow_regs[0x92] = 0x00;
4270 dev->shadow_regs[0x93] = 0x06;
4271 break;
4272 case A920_SENSOR:
4273 dev->shadow_regs[0x34] = 0x06;
4274 dev->shadow_regs[0x36] = 0x0f;
4275 dev->shadow_regs[0x38] = 0x09;
4276
4277 dev->shadow_regs[0x79] = 0x40;
4278
4279 dev->shadow_regs[0x80] = 0x0e;
4280 dev->shadow_regs[0x81] = 0x0e;
4281 dev->shadow_regs[0x82] = 0x00;
4282
4283 dev->shadow_regs[0x85] = 0x05;
4284 dev->shadow_regs[0x86] = 0x14;
4285 dev->shadow_regs[0x87] = 0x06;
4286 dev->shadow_regs[0x88] = 0x04;
4287
4288 dev->shadow_regs[0x91] = 0x60;
4289 dev->shadow_regs[0x92] = 0x85;
4290 dev->shadow_regs[0x93] = 0x0e;
4291 break;
4292 case X1200_SENSOR:
4293 dev->shadow_regs[0x34] = 0x07;
4294 dev->shadow_regs[0x36] = 0x0a;
4295 dev->shadow_regs[0x38] = 0x04;
4296
4297 /* data compression
4298 dev->shadow_regs[0x40] = 0x90;
4299 dev->shadow_regs[0x50] = 0x20; */
4300
4301 /* no data compression */
4302 dev->shadow_regs[0x40] = 0x80;
4303 dev->shadow_regs[0x50] = 0x00;
4304
4305 dev->shadow_regs[0x80] = 0x02;
4306 dev->shadow_regs[0x81] = 0x00;
4307 dev->shadow_regs[0x82] = 0x06;
4308 break;
4309 case X1200_USB2_SENSOR:
4310 dev->shadow_regs[0x34] = 0x0d;
4311 dev->shadow_regs[0x36] = 0x13;
4312 dev->shadow_regs[0x38] = 0x10;
4313
4314 dev->shadow_regs[0x80] = 0x04;
4315 dev->shadow_regs[0x81] = 0x0e;
4316 dev->shadow_regs[0x82] = 0x08;
4317
4318 dev->shadow_regs[0x85] = 0x02;
4319 dev->shadow_regs[0x86] = 0x3b;
4320 dev->shadow_regs[0x87] = 0x0f;
4321 dev->shadow_regs[0x88] = 0x24;
4322
4323 dev->shadow_regs[0x91] = 0x19;
4324 dev->shadow_regs[0x92] = 0x30;
4325 dev->shadow_regs[0x93] = 0x0e;
4326 dev->shadow_regs[0xc5] = 0x17;
4327 dev->shadow_regs[0xc6] = 0x09;
4328 dev->shadow_regs[0xca] = 0x0a;
4329 break;
4330 }
4331 switch (dev->model.motor_type)
4332 {
4333 case X74_MOTOR:
4334 /* Motor enable & Coordinate space denominator */
4335 dev->shadow_regs[0xc3] = 0x81;
4336 /* ? */
4337 dev->shadow_regs[0xc4] = 0x20;
4338 dev->shadow_regs[0xc5] = 0x21;
4339 /* Movement direction & step size */
4340 dev->shadow_regs[0xc6] = 0x09;
4341 dev->shadow_regs[0xc8] = 0x04;
4342 dev->shadow_regs[0xc9] = 0x39;
4343 dev->shadow_regs[0xca] = 0x20;
4344 /* bounds of movement range0 */
4345 dev->shadow_regs[0xe0] = 0x00;
4346 dev->shadow_regs[0xe1] = 0x00;
4347 /* step size range0 */
4348 dev->shadow_regs[0xe2] = 0xbf;
4349 /* ? */
4350 dev->shadow_regs[0xe3] = 0x05;
4351 /* bounds of movement range1 */
4352 dev->shadow_regs[0xe4] = 0x00;
4353 dev->shadow_regs[0xe5] = 0x00;
4354 /* step size range1 */
4355 dev->shadow_regs[0xe6] = 0x0d;
4356 /* bounds of movement range2 */
4357 dev->shadow_regs[0xe7] = 0x00;
4358 dev->shadow_regs[0xe8] = 0x00;
4359 /* step size range2 */
4360 dev->shadow_regs[0xe9] = 0x05;
4361 /* bounds of movement range3 */
4362 dev->shadow_regs[0xea] = 0x00;
4363 dev->shadow_regs[0xeb] = 0x00;
4364 /* step size range3 */
4365 dev->shadow_regs[0xec] = 0x01;
4366 /* bounds of movement range4 -only for 75dpi grayscale */
4367 dev->shadow_regs[0xed] = 0x00;
4368 dev->shadow_regs[0xee] = 0x00;
4369 /* step size range4 */
4370 dev->shadow_regs[0xef] = 0x01;
4371 break;
4372 case A920_MOTOR:
4373 case X1100_MOTOR:
4374 /* Motor enable & Coordinate space denominator */
4375 dev->shadow_regs[0xc3] = 0x86;
4376 /* ? */
4377 dev->shadow_regs[0xc5] = 0x27;
4378 /* Movement direction & step size */
4379 dev->shadow_regs[0xc6] = 0x0c;
4380 /* ? */
4381 dev->shadow_regs[0xc9] = 0x3a;
4382 dev->shadow_regs[0xca] = 0x1a;
4383 /* bounds of movement range0 */
4384 dev->shadow_regs[0xe0] = 0x57;
4385 dev->shadow_regs[0xe1] = 0x0a;
4386 /* step size range0 */
4387 dev->shadow_regs[0xe2] = 0xbf;
4388 /* ? */
4389 dev->shadow_regs[0xe3] = 0x05;
4390 /* bounds of movement range1 */
4391 dev->shadow_regs[0xe4] = 0x3b;
4392 dev->shadow_regs[0xe5] = 0x0a;
4393 /* step size range1 */
4394 dev->shadow_regs[0xe6] = 0x0e;
4395 /* bounds of movement range2 */
4396 dev->shadow_regs[0xe7] = 0x00;
4397 dev->shadow_regs[0xe8] = 0x00;
4398 /* step size range2 */
4399 dev->shadow_regs[0xe9] = 0x05;
4400 /* bounds of movement range3 */
4401 dev->shadow_regs[0xea] = 0x00;
4402 dev->shadow_regs[0xeb] = 0x00;
4403 /* step size range3 */
4404 dev->shadow_regs[0xec] = 0x01;
4405 /* step size range4 */
4406 dev->shadow_regs[0xef] = 0x01;
4407 break;
4408 }
4409 /* set colour scan */
4410 dev->shadow_regs[0x2f] = 0x11;
4411
4412 dev->shadow_regs[0x35] = 0x01;
4413 dev->shadow_regs[0x37] = 0x01;
4414
4415 /* set motor resolution divisor */
4416 dev->shadow_regs[0x39] = 0x03;
4417 /* set # of head moves per CIS read */
4418 rts88xx_set_scan_frequency (dev->shadow_regs, 2);
4419
4420
4421 }
4422 else
4423 {
4424 switch (dev->model.sensor_type)
4425 {
4426 case X74_SENSOR:
4427 dev->shadow_regs[0x2c] = 0x04;
4428 dev->shadow_regs[0x2d] = 0x46;
4429 dev->shadow_regs[0x34] = 0x05;
4430 dev->shadow_regs[0x35] = 0x05;
4431 dev->shadow_regs[0x36] = 0x0b;
4432 dev->shadow_regs[0x37] = 0x0b;
4433 dev->shadow_regs[0x38] = 0x11;
4434 dev->shadow_regs[0x40] = 0x40;
4435
4436 dev->shadow_regs[0x85] = 0x00;
4437 dev->shadow_regs[0x86] = 0x00;
4438 dev->shadow_regs[0x87] = 0x00;
4439 dev->shadow_regs[0x88] = 0x00;
4440
4441 dev->shadow_regs[0x91] = 0x00;
4442 dev->shadow_regs[0x92] = 0x00;
4443 dev->shadow_regs[0x93] = 0x06;
4444 break;
4445 case X1100_B2_SENSOR:
4446 dev->shadow_regs[0x34] = 0x11;
4447 dev->shadow_regs[0x35] = 0x11;
4448 dev->shadow_regs[0x36] = 0x21;
4449 dev->shadow_regs[0x37] = 0x21;
4450 dev->shadow_regs[0x38] = 0x31;
4451
4452 dev->shadow_regs[0x85] = 0x00;
4453 dev->shadow_regs[0x86] = 0x00;
4454 dev->shadow_regs[0x87] = 0x00;
4455 dev->shadow_regs[0x88] = 0x00;
4456
4457 dev->shadow_regs[0x91] = 0x00;
4458 dev->shadow_regs[0x92] = 0x00;
4459 dev->shadow_regs[0x93] = 0x06;
4460 break;
4461 case X1100_2C_SENSOR:
4462 dev->shadow_regs[0x34] = 0x07;
4463 dev->shadow_regs[0x35] = 0x07;
4464 dev->shadow_regs[0x36] = 0x0d;
4465 dev->shadow_regs[0x37] = 0x0d;
4466 dev->shadow_regs[0x38] = 0x13;
4467
4468 dev->shadow_regs[0x85] = 0x20;
4469 dev->shadow_regs[0x86] = 0x00;
4470 dev->shadow_regs[0x87] = 0x00;
4471 dev->shadow_regs[0x88] = 0x00;
4472
4473 dev->shadow_regs[0x91] = 0x00;
4474 dev->shadow_regs[0x92] = 0x00;
4475 dev->shadow_regs[0x93] = 0x06;
4476 break;
4477 case A920_SENSOR:
4478 dev->shadow_regs[0x34] = 0x05;
4479 dev->shadow_regs[0x35] = 0x05;
4480 dev->shadow_regs[0x36] = 0x0b;
4481 dev->shadow_regs[0x37] = 0x0b;
4482 dev->shadow_regs[0x38] = 0x11;
4483
4484 dev->shadow_regs[0x85] = 0x05;
4485 dev->shadow_regs[0x86] = 0x14;
4486 dev->shadow_regs[0x87] = 0x06;
4487 dev->shadow_regs[0x88] = 0x04;
4488
4489 dev->shadow_regs[0x91] = 0xe0;
4490 dev->shadow_regs[0x92] = 0x85;
4491 dev->shadow_regs[0x93] = 0x0e;
4492 break;
4493 case X1200_SENSOR:
4494 dev->shadow_regs[0x34] = 0x03;
4495 dev->shadow_regs[0x35] = 0x03;
4496 dev->shadow_regs[0x36] = 0x07;
4497 dev->shadow_regs[0x37] = 0x07;
4498 dev->shadow_regs[0x38] = 0x0b;
4499
4500 /* data compression
4501 dev->shadow_regs[0x40] = 0x90;
4502 dev->shadow_regs[0x50] = 0x20; */
4503 /* no data compression */
4504 dev->shadow_regs[0x40] = 0x80;
4505 dev->shadow_regs[0x50] = 0x00;
4506
4507 dev->shadow_regs[0x85] = 0x00;
4508 dev->shadow_regs[0x86] = 0x00;
4509 dev->shadow_regs[0x87] = 0xff;
4510 dev->shadow_regs[0x88] = 0x02;
4511
4512 dev->shadow_regs[0x92] = 0x00;
4513
4514 break;
4515 case X1200_USB2_SENSOR:
4516 dev->shadow_regs[0x34] = 0x03;
4517 dev->shadow_regs[0x35] = 0x03;
4518 dev->shadow_regs[0x36] = 0x07;
4519 dev->shadow_regs[0x37] = 0x07;
4520 dev->shadow_regs[0x38] = 0x0b;
4521
4522 dev->shadow_regs[0x40] = 0x80;
4523 dev->shadow_regs[0x50] = 0x00;
4524
4525 dev->shadow_regs[0x85] = 0x00;
4526 dev->shadow_regs[0x86] = 0x00;
4527 dev->shadow_regs[0x87] = 0xff;
4528 dev->shadow_regs[0x88] = 0x02;
4529
4530 dev->shadow_regs[0x92] = 0x00;
4531 break;
4532 }
4533 switch (dev->model.motor_type)
4534 {
4535 case X74_MOTOR:
4536 /* set # of head moves per CIS read */
4537 rts88xx_set_scan_frequency (dev->shadow_regs, 1);
4538 /* ? */
4539 dev->shadow_regs[0xc4] = 0x20;
4540 dev->shadow_regs[0xc5] = 0x22;
4541 /* Movement direction & step size */
4542 dev->shadow_regs[0xc6] = 0x0b;
4543
4544 dev->shadow_regs[0xc8] = 0x04;
4545 dev->shadow_regs[0xc9] = 0x39;
4546 dev->shadow_regs[0xca] = 0x1f;
4547
4548 /* bounds of movement range0 */
4549 dev->shadow_regs[0xe0] = 0x2f;
4550 dev->shadow_regs[0xe1] = 0x11;
4551 /* step size range0 */
4552 dev->shadow_regs[0xe2] = 0x9f;
4553 /* ? */
4554 dev->shadow_regs[0xe3] = 0x0f;
4555 /* bounds of movement range1 */
4556 dev->shadow_regs[0xe4] = 0xcb;
4557
4558 dev->shadow_regs[0xe5] = 0x10;
4559 /* step size range1 */
4560 dev->shadow_regs[0xe6] = 0x64;
4561 /* bounds of movement range2 */
4562 dev->shadow_regs[0xe7] = 0x00;
4563 dev->shadow_regs[0xe8] = 0x00;
4564 /* step size range2 */
4565 dev->shadow_regs[0xe9] = 0x32;
4566 /* bounds of movement range3 */
4567 dev->shadow_regs[0xea] = 0x00;
4568 dev->shadow_regs[0xeb] = 0x00;
4569 /* step size range3 */
4570 dev->shadow_regs[0xec] = 0x0c;
4571 /* bounds of movement range4 -only for 75dpi grayscale */
4572 dev->shadow_regs[0xed] = 0x00;
4573 dev->shadow_regs[0xee] = 0x00;
4574 /* step size range4 */
4575 dev->shadow_regs[0xef] = 0x08;
4576 break;
4577 case X1100_MOTOR:
4578 case A920_MOTOR:
4579 /* set ? only for colour? */
4580 dev->shadow_regs[0x80] = 0x00;
4581 dev->shadow_regs[0x81] = 0x00;
4582 dev->shadow_regs[0x82] = 0x00;
4583 /* ? */
4584 dev->shadow_regs[0xc5] = 0x22;
4585 /* Movement direction & step size */
4586 dev->shadow_regs[0xc6] = 0x09;
4587 /* ? */
4588 dev->shadow_regs[0xc9] = 0x3b;
4589 dev->shadow_regs[0xca] = 0x1f;
4590 /* bounds of movement range0 */
4591 dev->shadow_regs[0xe0] = 0xf7;
4592 dev->shadow_regs[0xe1] = 0x16;
4593 /* step size range0 */
4594 dev->shadow_regs[0xe2] = 0x87;
4595 /* ? */
4596 dev->shadow_regs[0xe3] = 0x13;
4597 /* bounds of movement range1 */
4598 dev->shadow_regs[0xe4] = 0x1b;
4599 dev->shadow_regs[0xe5] = 0x16;
4600 /* step size range1 */
4601 dev->shadow_regs[0xe6] = 0xdc;
4602 /* bounds of movement range2 */
4603 dev->shadow_regs[0xe7] = 0x00;
4604 dev->shadow_regs[0xe8] = 0x00;
4605 /* step size range2 */
4606 dev->shadow_regs[0xe9] = 0x1b;
4607 /* bounds of movement range3 */
4608 dev->shadow_regs[0xea] = 0x00;
4609 dev->shadow_regs[0xeb] = 0x00;
4610 /* step size range3 */
4611 dev->shadow_regs[0xec] = 0x07;
4612 /* step size range4 */
4613 dev->shadow_regs[0xef] = 0x03;
4614 break;
4615 }
4616
4617 /* set grayscale scan */
4618 dev->shadow_regs[0x2f] = 0x21;
4619
4620 /* set motor resolution divisor */
4621 dev->shadow_regs[0x39] = 0x01;
4622
4623 /* set # of head moves per CIS read */
4624 rts88xx_set_scan_frequency (dev->shadow_regs, 1);
4625
4626 /* Motor enable & Coordinate space denominator */
4627 dev->shadow_regs[0xc3] = 0x81;
4628 } /* else (grayscale) */
4629
4630 /* set horizontal resolution */
4631 dev->shadow_regs[0x79] = 0x40;
4632
4633 }
4634 /*600dpi x 1200dpi */
4635 if (resolution == 1200)
4636 {
4637 DBG (5, "sanei_lexmark_low_set_scan_regs(): 1200 DPI resolution\n");
4638
4639 /* 1200 dpi doesn't work for X74 yet */
4640 if (dev->model.sensor_type == X74_SENSOR)
4641 return SANE_STATUS_INVAL;
4642
4643 if (isColourScan)
4644 {
4645 /* set colour scan */
4646 dev->shadow_regs[0x2f] = 0x11;
4647 /* set motor resolution divisor */
4648 dev->shadow_regs[0x39] = 0x01;
4649 /* set # of head moves per CIS read */
4650 rts88xx_set_scan_frequency (dev->shadow_regs, 2);
4651
4652 if (dev->model.sensor_type == X1100_B2_SENSOR)
4653 {
4654 /* set ? */
4655 dev->shadow_regs[0x34] = 0x29;
4656 dev->shadow_regs[0x36] = 0x29;
4657 dev->shadow_regs[0x38] = 0x28;
4658 /* set ? */
4659 dev->shadow_regs[0x80] = 0x04;
4660 dev->shadow_regs[0x81] = 0x04;
4661 dev->shadow_regs[0x82] = 0x08;
4662 dev->shadow_regs[0x85] = 0x83;
4663 dev->shadow_regs[0x86] = 0x7e;
4664 dev->shadow_regs[0x87] = 0xad;
4665 dev->shadow_regs[0x88] = 0x35;
4666 dev->shadow_regs[0x91] = 0xfe;
4667 dev->shadow_regs[0x92] = 0xdf;
4668 }
4669 else
4670 { /* A920 case */
4671 dev->shadow_regs[0x34] = 0x0c;
4672 dev->shadow_regs[0x36] = 0x1e;
4673 dev->shadow_regs[0x38] = 0x10;
4674
4675 dev->shadow_regs[0x80] = 0x0c;
4676 dev->shadow_regs[0x81] = 0x08;
4677 dev->shadow_regs[0x82] = 0x0c;
4678
4679 dev->shadow_regs[0x85] = 0x05;
4680 dev->shadow_regs[0x86] = 0x14;
4681 dev->shadow_regs[0x87] = 0x06;
4682 dev->shadow_regs[0x88] = 0x04;
4683
4684 dev->shadow_regs[0x91] = 0x60;
4685 dev->shadow_regs[0x92] = 0x85;
4686 }
4687
4688 dev->shadow_regs[0x35] = 0x01;
4689 dev->shadow_regs[0x37] = 0x01;
4690 /* set motor resolution divisor */
4691 dev->shadow_regs[0x39] = 0x01;
4692 dev->shadow_regs[0x93] = 0x0e;
4693
4694 /* Motor enable & Coordinate space denominator */
4695 dev->shadow_regs[0xc3] = 0x86;
4696 /* ? */
4697 dev->shadow_regs[0xc5] = 0x41;
4698 /* Movement direction & step size */
4699 dev->shadow_regs[0xc6] = 0x0c;
4700 /* ? */
4701 dev->shadow_regs[0xc9] = 0x3a;
4702 dev->shadow_regs[0xca] = 0x40;
4703 /* bounds of movement range0 */
4704 dev->shadow_regs[0xe0] = 0x00;
4705 dev->shadow_regs[0xe1] = 0x00;
4706 /* step size range0 */
4707 dev->shadow_regs[0xe2] = 0x85;
4708 /* ? */
4709 dev->shadow_regs[0xe3] = 0x0b;
4710 /* bounds of movement range1 */
4711 dev->shadow_regs[0xe4] = 0x00;
4712 dev->shadow_regs[0xe5] = 0x00;
4713 /* step size range1 */
4714 dev->shadow_regs[0xe6] = 0x0e;
4715 /* bounds of movement range2 */
4716 dev->shadow_regs[0xe7] = 0x00;
4717 dev->shadow_regs[0xe8] = 0x00;
4718 /* step size range2 */
4719 dev->shadow_regs[0xe9] = 0x05;
4720 /* bounds of movement range3 */
4721 dev->shadow_regs[0xea] = 0x00;
4722 dev->shadow_regs[0xeb] = 0x00;
4723 /* step size range3 */
4724 dev->shadow_regs[0xec] = 0x01;
4725 /* step size range4 */
4726 dev->shadow_regs[0xef] = 0x01;
4727 }
4728 else
4729 {
4730 /* set grayscale scan */
4731 dev->shadow_regs[0x2f] = 0x21;
4732 /* set ? */
4733 dev->shadow_regs[0x34] = 0x22;
4734 dev->shadow_regs[0x35] = 0x22;
4735 dev->shadow_regs[0x36] = 0x42;
4736 dev->shadow_regs[0x37] = 0x42;
4737 dev->shadow_regs[0x38] = 0x62;
4738 /* set motor resolution divisor */
4739 dev->shadow_regs[0x39] = 0x01;
4740 /* set # of head moves per CIS read */
4741 rts88xx_set_scan_frequency (dev->shadow_regs, 0);
4742
4743 /* set ? only for colour? */
4744 dev->shadow_regs[0x80] = 0x00;
4745 dev->shadow_regs[0x81] = 0x00;
4746 dev->shadow_regs[0x82] = 0x00;
4747 dev->shadow_regs[0x85] = 0x00;
4748 dev->shadow_regs[0x86] = 0x00;
4749 dev->shadow_regs[0x87] = 0x00;
4750 dev->shadow_regs[0x88] = 0x00;
4751 dev->shadow_regs[0x91] = 0x00;
4752 dev->shadow_regs[0x92] = 0x00;
4753 dev->shadow_regs[0x93] = 0x06;
4754 /* Motor enable & Coordinate space denominator */
4755 dev->shadow_regs[0xc3] = 0x81;
4756 /* ? */
4757 dev->shadow_regs[0xc5] = 0x41;
4758 /* Movement direction & step size */
4759 dev->shadow_regs[0xc6] = 0x09;
4760 /* ? */
4761 dev->shadow_regs[0xc9] = 0x3a;
4762 dev->shadow_regs[0xca] = 0x40;
4763 /* bounds of movement range0 */
4764 dev->shadow_regs[0xe0] = 0x00;
4765 dev->shadow_regs[0xe1] = 0x00;
4766 /* step size range0 */
4767 dev->shadow_regs[0xe2] = 0xc7;
4768 /* ? */
4769 dev->shadow_regs[0xe3] = 0x29;
4770 /* bounds of movement range1 */
4771 dev->shadow_regs[0xe4] = 0x00;
4772 dev->shadow_regs[0xe5] = 0x00;
4773 /* step size range1 */
4774 dev->shadow_regs[0xe6] = 0xdc;
4775 /* bounds of movement range2 */
4776 dev->shadow_regs[0xe7] = 0x00;
4777 dev->shadow_regs[0xe8] = 0x00;
4778 /* step size range2 */
4779 dev->shadow_regs[0xe9] = 0x1b;
4780 /* bounds of movement range3 */
4781 dev->shadow_regs[0xea] = 0x00;
4782 dev->shadow_regs[0xeb] = 0x00;
4783 /* step size range3 */
4784 dev->shadow_regs[0xec] = 0x07;
4785 /* step size range4 */
4786 dev->shadow_regs[0xef] = 0x03;
4787 }
4788
4789 /* set horizontal resolution */
4790 dev->shadow_regs[0x79] = 0x40;
4791 }
4792
4793 /* is calibration has been done, we override fixed settings with detected ones */
4794 if (calibrated)
4795 {
4796 /* override fixed values with ones from calibration */
4797 if (rts88xx_is_color (dev->shadow_regs))
4798 {
4799 rts88xx_set_offset (dev->shadow_regs,
4800 dev->offset.red,
4801 dev->offset.green, dev->offset.blue);
4802 rts88xx_set_gain (dev->shadow_regs,
4803 dev->gain.red, dev->gain.green, dev->gain.blue);
4804 }
4805 else
4806 {
4807 rts88xx_set_offset (dev->shadow_regs,
4808 dev->offset.gray,
4809 dev->offset.gray, dev->offset.gray);
4810 rts88xx_set_gain (dev->shadow_regs,
4811 dev->gain.gray, dev->gain.gray, dev->gain.gray);
4812 }
4813 }
4814 DBG (2, "sanei_lexmark_low_set_scan_regs: end.\n");
4815 return SANE_STATUS_GOOD;
4816 }
4817
4818 SANE_Status
sanei_lexmark_low_start_scan(Lexmark_Device * dev)4819 sanei_lexmark_low_start_scan (Lexmark_Device * dev)
4820 {
4821 SANE_Int devnum;
4822
4823 static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 };
4824
4825 static SANE_Byte command5_block[] = { 0x80, 0xb3, 0x00, 0x01 };
4826
4827 SANE_Byte poll_result[3];
4828 SANE_Byte read_result;
4829 SANE_Bool scan_head_moving;
4830 size_t size;
4831
4832 devnum = dev->devnum;
4833
4834 dev->transfer_buffer = NULL; /* No data xferred yet */
4835 DBG (2, "sanei_lexmark_low_start_scan:\n");
4836
4837
4838 /* 80 b3 00 01 - poll for scanner not moving */
4839 scan_head_moving = SANE_TRUE;
4840 while (scan_head_moving)
4841 {
4842 size = 4;
4843 low_usb_bulk_write (devnum, command5_block, &size);
4844 size = 0x1;
4845 low_usb_bulk_read (devnum, &read_result, &size);
4846 if ((read_result & 0xF) == 0x0)
4847 {
4848 scan_head_moving = SANE_FALSE;
4849 }
4850 /* F.O. Should be a timeout here so we don't hang if something breaks */
4851 #ifdef FAKE_USB
4852 scan_head_moving = SANE_FALSE;
4853 #endif
4854 }
4855
4856 /* Clear C6 */
4857 low_clr_c6 (devnum);
4858 /* Stop the scanner */
4859 low_stop_mvmt (devnum);
4860
4861 /*Set regs x2 */
4862 dev->shadow_regs[0x32] = 0x00;
4863 low_write_all_regs (devnum, dev->shadow_regs);
4864 dev->shadow_regs[0x32] = 0x40;
4865 low_write_all_regs (devnum, dev->shadow_regs);
4866
4867 /* Start Scan */
4868 rts88xx_commit (devnum, dev->shadow_regs[0x2c]);
4869
4870 /* We start with 0 bytes remaining to be read */
4871 dev->bytes_remaining = 0;
4872 /* and 0 bytes in the transfer buffer */
4873 dev->bytes_in_buffer = 0;
4874 dev->bytes_read = 0;
4875
4876 /* Poll the available byte count until not 0 */
4877 while (1)
4878 {
4879 size = 4;
4880 low_usb_bulk_write (devnum, command4_block, &size);
4881 size = 0x3;
4882 low_usb_bulk_read (devnum, poll_result, &size);
4883 if (!
4884 (poll_result[0] == 0 && poll_result[1] == 0 && poll_result[2] == 0))
4885 {
4886 /* if result != 00 00 00 we got data */
4887
4888 /* data_size should be used to set bytes_remaining */
4889 /* data_size is set from sane_get_parameters () */
4890 dev->bytes_remaining = dev->data_size;
4891 /* Initialize the read buffer */
4892 read_buffer_init (dev, dev->params.bytes_per_line);
4893 return SANE_STATUS_GOOD;
4894
4895 }
4896 size = 4;
4897 /* I'm not sure why the Windows driver does this - probably a timeout? */
4898 low_usb_bulk_write (devnum, command5_block, &size);
4899 size = 0x1;
4900 low_usb_bulk_read (devnum, &read_result, &size);
4901 if (read_result != 0x68)
4902 {
4903 dev->bytes_remaining = 0;
4904 return SANE_STATUS_IO_ERROR;
4905 }
4906 }
4907
4908 DBG (2, "sanei_lexmark_low_start_scan: end.\n");
4909 return SANE_STATUS_GOOD;
4910 }
4911
4912 long
sanei_lexmark_low_read_scan_data(SANE_Byte * data,SANE_Int size,Lexmark_Device * dev)4913 sanei_lexmark_low_read_scan_data (SANE_Byte * data, SANE_Int size,
4914 Lexmark_Device * dev)
4915 {
4916 SANE_Bool isColourScan, isGrayScan;
4917 static SANE_Byte command1_block[] = { 0x91, 0x00, 0xff, 0xc0 };
4918 size_t cmd_size, xfer_request;
4919 long bytes_read;
4920 SANE_Bool even_byte;
4921 SANE_Status status;
4922 int i, k, val;
4923
4924 DBG (2, "sanei_lexmark_low_read_scan_data:\n");
4925
4926 /* colour mode */
4927 isGrayScan = SANE_FALSE;
4928 if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0)
4929 isColourScan = SANE_TRUE;
4930 else
4931 {
4932 isColourScan = SANE_FALSE;
4933 /* grayscale mode */
4934 if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) == 0)
4935 isGrayScan = SANE_TRUE;
4936 }
4937
4938 /* Check if we have a transfer buffer. Create one and fill it if we don't */
4939 if (dev->transfer_buffer == NULL)
4940 {
4941 if (dev->bytes_remaining > 0)
4942 {
4943 if (dev->bytes_remaining > MAX_XFER_SIZE)
4944 xfer_request = MAX_XFER_SIZE;
4945 else
4946 xfer_request = dev->bytes_remaining;
4947
4948 command1_block[2] = (SANE_Byte) (xfer_request >> 8);
4949 command1_block[3] = (SANE_Byte) (xfer_request & 0xFF);
4950
4951 /* wait for data */
4952 status = low_poll_data (dev->devnum);
4953 if (status != SANE_STATUS_GOOD)
4954 {
4955 DBG (1,
4956 "sanei_lexmark_low_read_scan_data: time-out while waiting for data.\n");
4957 return status;
4958 }
4959
4960 /* Create buffer to hold the amount we will request */
4961 dev->transfer_buffer = (SANE_Byte *) malloc (MAX_XFER_SIZE);
4962 if (dev->transfer_buffer == NULL)
4963 return SANE_STATUS_NO_MEM;
4964
4965 /* Fill it */
4966 /* Write: 91 00 (xfer_size) */
4967 cmd_size = 4;
4968 low_usb_bulk_write (dev->devnum, command1_block, &cmd_size);
4969
4970 /* Read: xfer_size bytes */
4971 cmd_size = xfer_request;
4972 low_usb_bulk_read (dev->devnum, dev->transfer_buffer, &cmd_size);
4973
4974 /* apply shading coefficients */
4975 k = dev->bytes_read % dev->read_buffer->linesize;
4976 for (i = 0; i < (int) cmd_size; i++)
4977 {
4978 val = dev->transfer_buffer[i];
4979 val = (int) ((float) val * dev->shading_coeff[k] + 0.5);
4980 if (val > 255)
4981 val = 255;
4982 dev->transfer_buffer[i] = val;
4983 k++;
4984 if ((size_t) k == dev->read_buffer->linesize)
4985 k = 0;
4986 }
4987
4988 /* advance by the amount actually read from device */
4989 dev->bytes_read += cmd_size;
4990 dev->bytes_remaining -= cmd_size;
4991 dev->bytes_in_buffer = cmd_size;
4992 dev->read_pointer = dev->transfer_buffer;
4993 DBG (2, "sanei_lexmark_low_read_scan_data:\n");
4994 DBG (2, " Filled a buffer from the scanner\n");
4995 DBG (2, " bytes_remaining: %lu\n", (u_long) dev->bytes_remaining);
4996 DBG (2, " bytes_in_buffer: %lu\n", (u_long) dev->bytes_in_buffer);
4997 DBG (2, " read_pointer: %p\n", dev->read_pointer);
4998 }
4999 }
5000
5001 DBG (5, "READ BUFFER INFO: \n");
5002 DBG (5, " write ptr: %p\n", dev->read_buffer->writeptr);
5003 DBG (5, " read ptr: %p\n", dev->read_buffer->readptr);
5004 DBG (5, " max write ptr: %p\n", dev->read_buffer->max_writeptr);
5005 DBG (5, " buffer size: %lu\n", (u_long) dev->read_buffer->size);
5006 DBG (5, " line size: %lu\n", (u_long) dev->read_buffer->linesize);
5007 DBG (5, " empty: %d\n", dev->read_buffer->empty);
5008 DBG (5, " line no: %d\n", dev->read_buffer->image_line_no);
5009
5010
5011 /* If there is space in the read buffer, copy the transfer buffer over */
5012 if (read_buffer_bytes_available (dev->read_buffer) >= dev->bytes_in_buffer)
5013 {
5014 even_byte = SANE_TRUE;
5015 while (dev->bytes_in_buffer)
5016 {
5017
5018 /* Colour Scan */
5019 if (isColourScan)
5020 {
5021 if (even_byte)
5022 read_buffer_add_byte (dev->read_buffer,
5023 dev->read_pointer + 1);
5024 else
5025 read_buffer_add_byte (dev->read_buffer,
5026 dev->read_pointer - 1);
5027 even_byte = !even_byte;
5028 }
5029 /* Gray Scan */
5030 else if (isGrayScan)
5031 {
5032 if (even_byte)
5033 read_buffer_add_byte_gray (dev->read_buffer,
5034 dev->read_pointer + 1);
5035 else
5036 read_buffer_add_byte_gray (dev->read_buffer,
5037 dev->read_pointer - 1);
5038 even_byte = !even_byte;
5039 }
5040 /* Lineart Scan */
5041 else
5042 {
5043 if (even_byte)
5044 read_buffer_add_bit_lineart (dev->read_buffer,
5045 dev->read_pointer + 1,
5046 dev->threshold);
5047 else
5048 read_buffer_add_bit_lineart (dev->read_buffer,
5049 dev->read_pointer - 1,
5050 dev->threshold);
5051 even_byte = !even_byte;
5052 }
5053 dev->read_pointer = dev->read_pointer + sizeof (SANE_Byte);
5054 dev->bytes_in_buffer--;
5055 }
5056 /* free the transfer buffer */
5057 free (dev->transfer_buffer);
5058 dev->transfer_buffer = NULL;
5059 }
5060
5061 DBG (5, "READ BUFFER INFO: \n");
5062 DBG (5, " write ptr: %p\n", dev->read_buffer->writeptr);
5063 DBG (5, " read ptr: %p\n", dev->read_buffer->readptr);
5064 DBG (5, " max write ptr: %p\n", dev->read_buffer->max_writeptr);
5065 DBG (5, " buffer size: %lu\n", (u_long) dev->read_buffer->size);
5066 DBG (5, " line size: %lu\n", (u_long) dev->read_buffer->linesize);
5067 DBG (5, " empty: %d\n", dev->read_buffer->empty);
5068 DBG (5, " line no: %d\n", dev->read_buffer->image_line_no);
5069
5070 /* Read blocks out of read buffer */
5071 bytes_read = read_buffer_get_bytes (dev->read_buffer, data, size);
5072
5073 DBG (2, "sanei_lexmark_low_read_scan_data:\n");
5074 DBG (2, " Copying lines from buffer to data\n");
5075 DBG (2, " bytes_remaining: %lu\n", (u_long) dev->bytes_remaining);
5076 DBG (2, " bytes_in_buffer: %lu\n", (u_long) dev->bytes_in_buffer);
5077 DBG (2, " read_pointer: %p\n", dev->read_buffer->readptr);
5078 DBG (2, " bytes_read %lu\n", (u_long) bytes_read);
5079
5080 /* if no more bytes to xfer and read buffer empty we're at the end */
5081 if ((dev->bytes_remaining == 0) && read_buffer_is_empty (dev->read_buffer))
5082 {
5083 if (!dev->eof)
5084 {
5085 DBG (2,
5086 "sanei_lexmark_low_read_scan_data: EOF- parking the scanner\n");
5087 dev->eof = SANE_TRUE;
5088 low_rewind (dev, dev->shadow_regs);
5089 }
5090 else
5091 {
5092 DBG (2, "ERROR: Why are we trying to set eof more than once?\n");
5093 }
5094 }
5095
5096 DBG (2, "sanei_lexmark_low_read_scan_data: end.\n");
5097 return bytes_read;
5098 }
5099
5100 void
low_rewind(Lexmark_Device * dev,SANE_Byte * regs)5101 low_rewind (Lexmark_Device * dev, SANE_Byte * regs)
5102 {
5103 SANE_Int new_location;
5104 SANE_Int location;
5105 SANE_Int scale;
5106
5107 DBG (2, "low_rewind: \n");
5108
5109 /* We rewind at 1200dpi resolution. We rely on content of shadow registers
5110 to compute the number of lines at 1200 dpi to go back */
5111
5112 /* first move to start of scanning area */
5113 scale = 600 / dev->val[OPT_RESOLUTION].w;
5114 new_location = ((dev->val[OPT_BR_Y].w / scale) * scale) * 2;
5115
5116 /* then add distance to go to the "origin dot" */
5117 if (rts88xx_is_color (regs))
5118 new_location += 400;
5119 else
5120 new_location += 420;
5121
5122 if (dev->model.sensor_type == X74_SENSOR)
5123 new_location += 150;
5124
5125
5126 location = new_location - 1;
5127 DBG (2, "low_rewind: %d=>new_location=%d\n", dev->val[OPT_BR_Y].w,
5128 new_location);
5129
5130 /* stops any pending scan */
5131 low_clr_c6 (dev->devnum);
5132 low_cancel (dev->devnum);
5133
5134 /* set regs for rewind */
5135 regs[0x2f] = 0xa1;
5136 regs[0x32] = 0x00;
5137 regs[0x39] = 0x00;
5138
5139 /* all other regs are always the same. these ones change with parameters */
5140 /* the following 4 regs are the location 61,60 and the location+1 63,62 */
5141
5142 regs[0x60] = LOBYTE (location);
5143 regs[0x61] = HIBYTE (location);
5144 regs[0x62] = LOBYTE (new_location);
5145 regs[0x63] = HIBYTE (new_location);
5146
5147 switch (dev->model.motor_type)
5148 {
5149 case X74_MOTOR:
5150 regs[0xc3] = 0x81;
5151 regs[0xc6] = 0x03;
5152 regs[0xc9] = 0x39;
5153 regs[0xe0] = 0x81;
5154 regs[0xe1] = 0x16;
5155 regs[0xe2] = 0xe1;
5156 regs[0xe3] = 0x04;
5157 regs[0xe4] = 0xe7;
5158 regs[0xe5] = 0x14;
5159 regs[0xe6] = 0x64;
5160 regs[0xe7] = 0xd5;
5161 regs[0xe8] = 0x08;
5162 regs[0xe9] = 0x32;
5163 regs[0xea] = 0xed;
5164 regs[0xeb] = 0x04;
5165 regs[0xec] = 0x0c;
5166 regs[0xef] = 0x08;
5167 break;
5168 case X1100_MOTOR:
5169 case A920_MOTOR:
5170 /* set regs for rewind */
5171 regs[0x79] = 0x40;
5172 regs[0xb2] = 0x04;
5173 regs[0xc3] = 0x81;
5174 regs[0xc6] = 0x01;
5175 regs[0xc9] = 0x3b;
5176 regs[0xe0] = 0x2b;
5177 regs[0xe1] = 0x17;
5178 regs[0xe2] = 0xe7;
5179 regs[0xe3] = 0x03;
5180 regs[0xe6] = 0xdc;
5181 regs[0xe7] = 0xb3;
5182 regs[0xe8] = 0x07;
5183 regs[0xe9] = 0x1b;
5184 regs[0xea] = 0x00;
5185 regs[0xeb] = 0x00;
5186 regs[0xec] = 0x07;
5187 regs[0xef] = 0x03;
5188 break;
5189 }
5190
5191
5192 /* starts scan */
5193 low_start_scan (dev->devnum, regs);
5194 DBG (2, "low_rewind: end.\n");
5195 }
5196
5197
5198 SANE_Status
read_buffer_init(Lexmark_Device * dev,int bytesperline)5199 read_buffer_init (Lexmark_Device * dev, int bytesperline)
5200 {
5201 size_t no_lines_in_buffer;
5202
5203 DBG (2, "read_buffer_init: Start\n");
5204
5205 dev->read_buffer = (Read_Buffer *) malloc (sizeof (Read_Buffer));
5206 if (dev->read_buffer == NULL)
5207 return SANE_STATUS_NO_MEM;
5208 dev->read_buffer->linesize = bytesperline;
5209 dev->read_buffer->gray_offset = 0;
5210 dev->read_buffer->max_gray_offset = bytesperline - 1;
5211 dev->read_buffer->region = RED;
5212 dev->read_buffer->red_offset = 0;
5213 dev->read_buffer->green_offset = 1;
5214 dev->read_buffer->blue_offset = 2;
5215 dev->read_buffer->max_red_offset = bytesperline - 3;
5216 dev->read_buffer->max_green_offset = bytesperline - 2;
5217 dev->read_buffer->max_blue_offset = bytesperline - 1;
5218 no_lines_in_buffer = 3 * MAX_XFER_SIZE / bytesperline;
5219 dev->read_buffer->size = bytesperline * no_lines_in_buffer;
5220 dev->read_buffer->data = (SANE_Byte *) malloc (dev->read_buffer->size);
5221 if (dev->read_buffer->data == NULL)
5222 return SANE_STATUS_NO_MEM;
5223 dev->read_buffer->readptr = dev->read_buffer->data;
5224 dev->read_buffer->writeptr = dev->read_buffer->data;
5225 dev->read_buffer->max_writeptr = dev->read_buffer->data +
5226 (no_lines_in_buffer - 1) * bytesperline;
5227 dev->read_buffer->empty = SANE_TRUE;
5228 dev->read_buffer->image_line_no = 0;
5229 dev->read_buffer->bit_counter = 0;
5230 dev->read_buffer->max_lineart_offset = dev->params.pixels_per_line - 1;
5231 return SANE_STATUS_GOOD;
5232 }
5233
5234 SANE_Status
read_buffer_free(Read_Buffer * read_buffer)5235 read_buffer_free (Read_Buffer * read_buffer)
5236 {
5237 DBG (2, "read_buffer_free:\n");
5238 if (read_buffer)
5239 {
5240 free (read_buffer->data);
5241 free (read_buffer);
5242 read_buffer = NULL;
5243 }
5244 return SANE_STATUS_GOOD;
5245 }
5246
5247 size_t
read_buffer_bytes_available(Read_Buffer * rb)5248 read_buffer_bytes_available (Read_Buffer * rb)
5249 {
5250
5251 DBG (2, "read_buffer_bytes_available:\n");
5252
5253 if (rb->empty)
5254 return rb->size;
5255 else if ((size_t) abs (rb->writeptr - rb->readptr) < rb->linesize)
5256 return 0; /* ptrs are less than one line apart */
5257 else if (rb->writeptr < rb->readptr)
5258 return (rb->readptr - rb->writeptr - rb->linesize);
5259 else
5260 return (rb->size + rb->readptr - rb->writeptr - rb->linesize);
5261 }
5262
5263 SANE_Status
read_buffer_add_byte(Read_Buffer * rb,SANE_Byte * byte_pointer)5264 read_buffer_add_byte (Read_Buffer * rb, SANE_Byte * byte_pointer)
5265 {
5266
5267 /* DBG(2, "read_buffer_add_byte:\n"); */
5268 /* F.O. Need to fix the endian byte ordering here */
5269
5270 switch (rb->region)
5271 {
5272 case RED:
5273 *(rb->writeptr + rb->red_offset) = *byte_pointer;
5274 if (rb->red_offset == rb->max_red_offset)
5275 {
5276 rb->red_offset = 0;
5277 rb->region = GREEN;
5278 }
5279 else
5280 rb->red_offset = rb->red_offset + (3 * sizeof (SANE_Byte));
5281 return SANE_STATUS_GOOD;
5282 case GREEN:
5283 *(rb->writeptr + rb->green_offset) = *byte_pointer;
5284 if (rb->green_offset == rb->max_green_offset)
5285 {
5286 rb->green_offset = 1;
5287 rb->region = BLUE;
5288 }
5289 else
5290 rb->green_offset = rb->green_offset + (3 * sizeof (SANE_Byte));
5291 return SANE_STATUS_GOOD;
5292 case BLUE:
5293 *(rb->writeptr + rb->blue_offset) = *byte_pointer;
5294 if (rb->blue_offset == rb->max_blue_offset)
5295 {
5296 rb->image_line_no++;
5297 /* finished a line. read_buffer no longer empty */
5298 rb->empty = SANE_FALSE;
5299 rb->blue_offset = 2;
5300 rb->region = RED;
5301 if (rb->writeptr == rb->max_writeptr)
5302 rb->writeptr = rb->data; /* back to beginning of buffer */
5303 else
5304 rb->writeptr = rb->writeptr + rb->linesize; /* next line */
5305 }
5306 else
5307 rb->blue_offset = rb->blue_offset + (3 * sizeof (SANE_Byte));
5308 return SANE_STATUS_GOOD;
5309 }
5310 return SANE_STATUS_GOOD;
5311 }
5312
5313 SANE_Status
read_buffer_add_byte_gray(Read_Buffer * rb,SANE_Byte * byte_pointer)5314 read_buffer_add_byte_gray (Read_Buffer * rb, SANE_Byte * byte_pointer)
5315 {
5316
5317 /* DBG(2, "read_buffer_add_byte_gray:\n"); */
5318
5319 *(rb->writeptr + rb->gray_offset) = *byte_pointer;
5320
5321 if (rb->gray_offset == rb->max_gray_offset)
5322 {
5323 rb->image_line_no++;
5324 /* finished a line. read_buffer no longer empty */
5325 rb->empty = SANE_FALSE;
5326 rb->gray_offset = 0;
5327
5328 if (rb->writeptr == rb->max_writeptr)
5329 rb->writeptr = rb->data; /* back to beginning of buffer */
5330 else
5331 rb->writeptr = rb->writeptr + rb->linesize; /* next line */
5332 }
5333 else
5334 rb->gray_offset = rb->gray_offset + (1 * sizeof (SANE_Byte));
5335 return SANE_STATUS_GOOD;
5336 }
5337
5338 SANE_Status
read_buffer_add_bit_lineart(Read_Buffer * rb,SANE_Byte * byte_pointer,SANE_Byte threshold)5339 read_buffer_add_bit_lineart (Read_Buffer * rb, SANE_Byte * byte_pointer,
5340 SANE_Byte threshold)
5341 {
5342 SANE_Byte tmpByte;
5343 SANE_Byte *currentBytePtr;
5344 SANE_Int bitIndex;
5345
5346 /* DBG(2, "read_buffer_add_bit_lineart:\n"); */
5347
5348 /* threshold = 0x80; */
5349 tmpByte = 0;
5350 /* Create a bit by comparing incoming byte to threshold */
5351 if (*byte_pointer <= threshold)
5352 {
5353 tmpByte = 128;
5354 }
5355
5356 /* Calculate the bit index in the current byte */
5357 bitIndex = rb->bit_counter % 8;
5358 /* Move the bit to its correct position in the temporary byte */
5359 tmpByte = tmpByte >> bitIndex;
5360 /* Get the pointer to the current byte */
5361 currentBytePtr = rb->writeptr + rb->gray_offset;
5362
5363 /* If this is the first write to this byte, clear the byte */
5364 if (bitIndex == 0)
5365 *currentBytePtr = 0;
5366 /* Set the value of the bit in the current byte */
5367 *currentBytePtr = *currentBytePtr | tmpByte;
5368
5369 /* last bit in the line? */
5370 if (rb->bit_counter == rb->max_lineart_offset)
5371 {
5372 /* Check if we're at the last byte of the line - error if not */
5373 if (rb->gray_offset != rb->max_gray_offset)
5374 {
5375 DBG (5, "read_buffer_add_bit_lineart:\n");
5376 DBG (5, " Last bit of line is not last byte.\n");
5377 DBG (5, " Bit Index: %d, Byte Index: %d. \n", rb->bit_counter,
5378 rb->max_gray_offset);
5379 return SANE_STATUS_INVAL;
5380 }
5381 rb->image_line_no++;
5382 /* line finished read_buffer no longer empty */
5383 rb->empty = SANE_FALSE;
5384 rb->gray_offset = 0;
5385 /* are we at the last line in the read buffer ? */
5386 if (rb->writeptr == rb->max_writeptr)
5387 rb->writeptr = rb->data; /* back to beginning of buffer */
5388 else
5389 rb->writeptr = rb->writeptr + rb->linesize; /* next line */
5390 /* clear the bit counter */
5391 rb->bit_counter = 0;
5392 }
5393 /* last bit in the byte? */
5394 else if (bitIndex == 7)
5395 {
5396 /* Not at the end of the line, but byte done. Increment byte offset */
5397 rb->gray_offset = rb->gray_offset + (1 * sizeof (SANE_Byte));
5398 /* increment bit counter */
5399 rb->bit_counter++;
5400 }
5401 else
5402 {
5403 /* else increment bit counter */
5404 rb->bit_counter++;
5405 }
5406
5407 return SANE_STATUS_GOOD;
5408 }
5409
5410
5411 size_t
read_buffer_get_bytes(Read_Buffer * rb,SANE_Byte * buffer,size_t rqst_size)5412 read_buffer_get_bytes (Read_Buffer * rb, SANE_Byte * buffer, size_t rqst_size)
5413 {
5414 /* Read_Buffer *rb; */
5415 size_t available_bytes;
5416
5417 /* rb = read_buffer; */
5418 if (rb->empty)
5419 return 0;
5420 else if (rb->writeptr > rb->readptr)
5421 {
5422 available_bytes = rb->writeptr - rb->readptr;
5423 if (available_bytes <= rqst_size)
5424 {
5425 /* We can read from the read pointer up to the write pointer */
5426 memcpy (buffer, rb->readptr, available_bytes);
5427 rb->readptr = rb->writeptr;
5428 rb->empty = SANE_TRUE;
5429 return available_bytes;
5430 }
5431 else
5432 {
5433 /* We can read from the full request size */
5434 memcpy (buffer, rb->readptr, rqst_size);
5435 rb->readptr = rb->readptr + rqst_size;
5436 return rqst_size;
5437 }
5438 }
5439 else
5440 {
5441 /* The read pointer is ahead of the write pointer. Its wrapped around. */
5442 /* We can read to the end of the buffer and make a recursive call to */
5443 /* read any available lines at the beginning of the buffer */
5444 available_bytes = rb->data + rb->size - rb->readptr;
5445 if (available_bytes <= rqst_size)
5446 {
5447 /* We can read from the read pointer up to the end of the buffer */
5448 memcpy (buffer, rb->readptr, available_bytes);
5449 rb->readptr = rb->data;
5450 if (rb->writeptr == rb->readptr)
5451 rb->empty = SANE_TRUE;
5452 return available_bytes +
5453 read_buffer_get_bytes (rb, buffer + available_bytes,
5454 rqst_size - available_bytes);
5455 }
5456 else
5457 {
5458 /* We can read from the full request size */
5459 memcpy (buffer, rb->readptr, rqst_size);
5460 rb->readptr = rb->readptr + rqst_size;
5461 return rqst_size;
5462 }
5463 }
5464 }
5465
5466 SANE_Bool
read_buffer_is_empty(Read_Buffer * read_buffer)5467 read_buffer_is_empty (Read_Buffer * read_buffer)
5468 {
5469 return read_buffer->empty;
5470 }
5471
5472 /*
5473 * average a width*height rgb/monochrome area
5474 * return values in given pointers
5475 */
5476 static int
average_area(SANE_Byte * regs,SANE_Byte * data,int width,int height,int * ra,int * ga,int * ba)5477 average_area (SANE_Byte * regs, SANE_Byte * data, int width, int height,
5478 int *ra, int *ga, int *ba)
5479 {
5480 int x, y;
5481 int global = 0;
5482 int rc, gc, bc;
5483
5484 *ra = 0;
5485 *ga = 0;
5486 *ba = 0;
5487 rc = 0;
5488 gc = 0;
5489 bc = 0;
5490 if (rts88xx_is_color (regs))
5491 {
5492 for (x = 0; x < width; x++)
5493 for (y = 0; y < height; y++)
5494 {
5495 rc += data[3 * width * y + x];
5496 gc += data[3 * width * y + width + x];
5497 bc += data[3 * width * y + 2 * width + x];
5498 }
5499 global = (rc + gc + bc) / (3 * width * height);
5500 *ra = rc / (width * height);
5501 *ga = gc / (width * height);
5502 *ba = bc / (width * height);
5503 }
5504 else
5505 {
5506 for (x = 0; x < width; x++)
5507 for (y = 0; y < height; y++)
5508 {
5509 gc += data[width * y + x];
5510 }
5511 global = gc / (width * height);
5512 *ga = gc / (width * height);
5513 }
5514 DBG (7, "average_area: global=%d, red=%d, green=%d, blue=%d\n", global, *ra,
5515 *ga, *ba);
5516 return global;
5517 }
5518
5519 /**
5520 * we scan a dark area with gain minimum to detect offset
5521 */
5522 SANE_Status
sanei_lexmark_low_offset_calibration(Lexmark_Device * dev)5523 sanei_lexmark_low_offset_calibration (Lexmark_Device * dev)
5524 {
5525 SANE_Byte regs[255]; /* we have our own copy of shadow registers */
5526 SANE_Status status = SANE_STATUS_GOOD;
5527 int i, lines = 8, yoffset = 2;
5528 int pixels;
5529 int failed = 0;
5530 /* offsets */
5531 int ro = 0, go = 0, bo = 0;
5532 /* averages */
5533 int ra, ga, ba, average;
5534 SANE_Byte *data = NULL;
5535 SANE_Byte top[OFFSET_RANGES] = { 0, 0x7f, 0x9f, 0xbf, 0xff };
5536 #ifdef DEEP_DEBUG
5537 char title[20];
5538 #endif
5539
5540 DBG (2, "sanei_lexmark_low_offset_calibration: start\n");
5541 /* copy registers */
5542 for (i = 0; i < 255; i++)
5543 regs[i] = dev->shadow_regs[i];
5544
5545 /* we clear movement bit */
5546 regs[0xc3] = regs[0xc3] & 0x7f;
5547
5548 pixels =
5549 (dev->sensor->offset_endx - dev->sensor->offset_startx) / regs[0x7a];
5550
5551 /* there are 4 ranges of offset:
5552 00-7F : almost no offset
5553 80-9F : high noise
5554 A0-BF : high noise
5555 C0-FF : high noise
5556 we start with the highest one and decrease until
5557 overall offset is ok
5558 First loop may have such an high offset that scanned data overflow
5559 and gives a low average. So we always skip its results
5560 */
5561
5562 /* minimal gains */
5563 DBG (3,
5564 "sanei_lexmark_low_offset_calibration: setting gains to (1,1,1).\n");
5565 rts88xx_set_gain (regs, 1, 1, 1);
5566
5567 i = OFFSET_RANGES;
5568 average = 255;
5569
5570 /* loop on ranges until one fits. Then adjust offset, first loop is
5571 * always done. TODO detect overflow by 'noise looking' data pattern */
5572 while (((i > 0) && (average > dev->sensor->offset_threshold))
5573 || (i == OFFSET_RANGES))
5574 {
5575 /* next range */
5576 i--;
5577
5578 /* sets to top of range */
5579 ro = top[i];
5580 go = top[i];
5581 bo = top[i];
5582 rts88xx_set_offset (regs, ro, ro, ro);
5583 DBG (3,
5584 "sanei_lexmark_low_offset_calibration: setting offsets to (%d,%d,%d).\n",
5585 ro, ro, ro);
5586
5587 status =
5588 low_simple_scan (dev, regs, dev->sensor->offset_startx, pixels,
5589 yoffset, lines, &data);
5590 if (status != SANE_STATUS_GOOD)
5591 {
5592 DBG (1,
5593 "sanei_lexmark_low_offset_calibration: low_simple_scan failed!\n");
5594 if (data != NULL)
5595 free (data);
5596 return status;
5597 }
5598 #ifdef DEEP_DEBUG
5599 sprintf (title, "offset%02x.pnm", ro);
5600 write_pnm_file (title, pixels, lines, rts88xx_is_color (regs), data);
5601 #endif
5602 average = average_area (regs, data, pixels, lines, &ra, &ga, &ba);
5603 free (data);
5604 }
5605 if (i == 0)
5606 {
5607 DBG (2, "sanei_lexmark_low_offset_calibration: failed !\n");
5608 failed = 1;
5609 }
5610
5611 /* increase gain and scan again */
5612 /* increase gain for fine offset tuning */
5613 rts88xx_set_gain (regs, 6, 6, 6);
5614 status =
5615 low_simple_scan (dev, regs, dev->sensor->offset_startx, pixels, yoffset,
5616 lines, &data);
5617 if (status != SANE_STATUS_GOOD)
5618 {
5619 DBG (1,
5620 "sanei_lexmark_low_offset_calibration: low_simple_scan failed!\n");
5621 if (data != NULL)
5622 free (data);
5623 return status;
5624 }
5625 average_area (regs, data, pixels, lines, &ra, &ga, &ba);
5626 #ifdef DEEP_DEBUG
5627 write_pnm_file ("offset-final.pnm", pixels, lines, rts88xx_is_color (regs),
5628 data);
5629 #endif
5630
5631 /* this "law" is a guess, may (should?) be changed ... */
5632 if (!failed)
5633 {
5634 if (ro > ra)
5635 dev->offset.red = ro - ra;
5636 if (go > ga)
5637 {
5638 dev->offset.green = go - ga;
5639 dev->offset.gray = go - ga;
5640 }
5641 if (bo > ba)
5642 dev->offset.blue = bo - ba;
5643 }
5644 else
5645 {
5646 dev->offset.red = dev->sensor->offset_fallback;
5647 dev->offset.green = dev->sensor->offset_fallback;
5648 dev->offset.blue = dev->sensor->offset_fallback;
5649 }
5650 DBG (7,
5651 "sanei_lexmark_low_offset_calibration: offset=(0x%02x,0x%02x,0x%02x).\n",
5652 dev->offset.red, dev->offset.green, dev->offset.blue);
5653
5654 DBG (2, "sanei_lexmark_low_offset_calibration: end.\n");
5655 free (data);
5656 return status;
5657 }
5658
5659 /*
5660 * we scan a white area until average is good enough
5661 * level is good enough when it maximize the range value of output:
5662 * ie max-min is maximum
5663 */
5664 SANE_Status
sanei_lexmark_low_gain_calibration(Lexmark_Device * dev)5665 sanei_lexmark_low_gain_calibration (Lexmark_Device * dev)
5666 {
5667 SANE_Byte regs[255]; /* we have our own copy of shadow registers */
5668 SANE_Status status = SANE_STATUS_GOOD;
5669 int i, lines = 4, yoffset = 1;
5670 int sx, ex;
5671 int pixels;
5672 /* averages */
5673 int ra, ga, ba;
5674 SANE_Byte *data = NULL;
5675 int red, green, blue;
5676 #ifdef DEEP_DEBUG
5677 char title[20];
5678 #endif
5679
5680 DBG (2, "sanei_lexmark_low_gain_calibration: start\n");
5681 /* copy registers */
5682 for (i = 0; i < 255; i++)
5683 regs[i] = dev->shadow_regs[i];
5684
5685 /* we clear movement bit */
5686 regs[0xc3] = regs[0xc3] & 0x7f;
5687 sx = regs[0x67] * 256 + regs[0x66];
5688 ex = regs[0x6d] * 256 + regs[0x6c];
5689 pixels = (ex - sx) / regs[0x7a];
5690
5691
5692 /* set up initial gains */
5693 red = 6;
5694 green = 6;
5695 blue = 6;
5696 rts88xx_set_gain (regs, red, green, blue);
5697
5698 /* init loop */
5699 i = 0;
5700 ra = 0;
5701 ba = 0;
5702 ga = 0;
5703
5704 status = low_cancel (dev->devnum);
5705 if (status != SANE_STATUS_GOOD)
5706 return status;
5707
5708 /* we do a simple scan all 3 averages give the chosen level */
5709 while (((rts88xx_is_color (regs)
5710 && ((ra < dev->sensor->red_gain_target)
5711 || (ga < dev->sensor->green_gain_target)
5712 || (ba < dev->sensor->blue_gain_target)))
5713 || (!rts88xx_is_color (regs)
5714 && (ga < dev->sensor->gray_gain_target))) && (i < 25))
5715 {
5716 status = low_simple_scan (dev, regs, sx, pixels, yoffset, lines, &data);
5717 if (status != SANE_STATUS_GOOD)
5718 {
5719 DBG (1,
5720 "sanei_lexmark_low_gain_calibration: low_simple_scan failed!\n");
5721 if (data != NULL)
5722 free (data);
5723 return status;
5724 }
5725 #ifdef DEEP_DEBUG
5726 sprintf (title, "gain%02d.pnm", i);
5727 write_pnm_file (title, pixels, lines, rts88xx_is_color (regs), data);
5728 #endif
5729 average_area (regs, data, pixels, lines, &ra, &ga, &ba);
5730 free (data);
5731 if (ra < dev->sensor->red_gain_target)
5732 red++;
5733 if (ga < dev->sensor->green_gain_target
5734 || (dev->sensor->gray_gain_target && !rts88xx_is_color (regs)))
5735 green++;
5736 if (ba < dev->sensor->blue_gain_target)
5737 blue++;
5738 rts88xx_set_gain (regs, red, green, blue);
5739 i++;
5740 }
5741 dev->gain.red = red;
5742 dev->gain.green = green;
5743 dev->gain.blue = blue;
5744 dev->gain.gray = green;
5745 DBG (7,
5746 "sanei_lexmark_low_gain_calibration: gain=(0x%02x,0x%02x,0x%02x).\n",
5747 dev->gain.red, dev->gain.green, dev->gain.blue);
5748 DBG (2, "sanei_lexmark_low_gain_calibration: end.\n");
5749 return status;
5750 }
5751
5752 /**
5753 * there is no hardware shading correction. So we have to do it in software.
5754 * We do it by scanning a pure white area which is before scanning area. Then
5755 * we compute per pixel coefficient to move the scanned value to the target
5756 * value. These coefficients are used later to correct scanned data.
5757 * The scan is done with all the final scan settings but the height and vertical
5758 * start position.
5759 */
5760 SANE_Status
sanei_lexmark_low_shading_calibration(Lexmark_Device * dev)5761 sanei_lexmark_low_shading_calibration (Lexmark_Device * dev)
5762 {
5763 SANE_Byte regs[255]; /* we have our own copy of shadow registers */
5764 int i, j, pixels, bpl;
5765 int sx, ex;
5766 SANE_Byte *data = NULL;
5767 SANE_Status status;
5768 /* enough 75 dpi lines to "go off" home position dot,
5769 and include shading area */
5770 int lines = 4 + 4;
5771 int lineoffset = 1;
5772 int linetotal = lines + lineoffset;
5773 int yoffset;
5774 int x, y;
5775 float rtarget, btarget, gtarget;
5776
5777 DBG (2, "sanei_lexmark_low_shading_calibration: start\n");
5778 /* copy registers */
5779 for (i = 0; i < 255; i++)
5780 regs[i] = dev->shadow_regs[i];
5781
5782 /* allocate memory for scan */
5783 sx = regs[0x67] * 256 + regs[0x66];
5784 ex = regs[0x6d] * 256 + regs[0x6c];
5785
5786
5787 DBG (7, "startx=%d, endx=%d, coef=%d, r2f=0x%02x\n",
5788 sx, ex, regs[0x7a], regs[0x2f]);
5789
5790 pixels = (ex - sx) / regs[0x7a];
5791 if (rts88xx_is_color (regs))
5792 bpl = 3 * pixels;
5793 else
5794 bpl = pixels;
5795
5796 /* adjust the target area to the scanning resolution */
5797 lines = (8 * lines) / regs[0x7a];
5798 lineoffset = (8 * lineoffset) / regs[0x7a];
5799 linetotal = (8 * linetotal) / regs[0x7a];
5800
5801 data = (SANE_Byte *) malloc (bpl * lines);
5802 DBG (7, "pixels=%d, lines=%d, size=%d\n", pixels, lines, bpl * lines);
5803 if (data == NULL)
5804 {
5805 DBG (2,
5806 "sanei_lexmark_low_shading_calibration: failed to allocate %d bytes !\n",
5807 bpl * lines);
5808 return SANE_STATUS_NO_MEM;
5809 }
5810 if (dev->shading_coeff != NULL)
5811 free (dev->shading_coeff);
5812 dev->shading_coeff = (float *) malloc (bpl * sizeof (float));
5813 if (dev->shading_coeff == NULL)
5814 {
5815 DBG (2,
5816 "sanei_lexmark_low_shading_calibration: failed to allocate %d floats !\n",
5817 bpl);
5818 free (data);
5819 return SANE_STATUS_NO_MEM;
5820 }
5821
5822 /* we set movement bit this time */
5823 regs[0xc3] = regs[0xc3] | 0x80;
5824
5825 /* execute scan */
5826 status = low_simple_scan (dev, regs, sx, pixels, lineoffset, lines, &data);
5827 if (status != SANE_STATUS_GOOD)
5828 {
5829 DBG (1,
5830 "sanei_lexmark_low_shading_calibration: low_simple_scan failed!\n");
5831 if (data != NULL)
5832 free (data);
5833 return status;
5834 }
5835
5836 yoffset = -1;
5837 /* the very first lines of the scan may include the dark dot used
5838 * locate park position. We find the first line free of it in the scan.
5839 * We can't use is_home_line since it modifies data.
5840 */
5841 for (y = 0; (y < lines) && (yoffset == y - 1); y++)
5842 {
5843 if (rts88xx_is_color (regs))
5844 {
5845 for (x = 0; x < 3 * pixels; x++)
5846 {
5847 if (data[x + y * 3 * pixels] < 30)
5848 yoffset = y;
5849 }
5850 }
5851 else
5852 {
5853 for (x = 0; x < pixels; x++)
5854 {
5855 if (data[x + y * pixels] < 30)
5856 yoffset = y;
5857 }
5858 }
5859 }
5860 /* make sure we are really out of the dot */
5861 yoffset++;
5862
5863 /* yoffset is index of last dot line, go to first white line */
5864 if (yoffset >= lines - 1)
5865 {
5866 DBG (7,
5867 "sanei_lexmark_low_shading_calibration: failed to detect yoffset.\n");
5868 /* fail safe fallback, picture will be altered at dot position,
5869 but scanner is safe */
5870 yoffset = lines - 2;
5871 }
5872 else
5873 yoffset++;
5874 DBG (7, "sanei_lexmark_low_shading_calibration: yoffset=%d.\n", yoffset);
5875
5876 #ifdef DEEP_DEBUG
5877 write_pnm_file ("shading.pnm", pixels, lines, rts88xx_is_color (regs),
5878 data);
5879 #endif
5880
5881 /* computes coefficients */
5882 /* there are 8 lines usable for shading calibration at 150 dpi, between
5883 bottom of "home position" dot and the start of the scanner's window
5884 assembly, we only use 7 of them */
5885 if (yoffset + (8 * 4) / regs[0x7a] < lines)
5886 lines = yoffset + (8 * 4) / regs[0x7a];
5887 rtarget = dev->sensor->red_shading_target;
5888 gtarget = dev->sensor->green_shading_target;
5889 btarget = dev->sensor->blue_shading_target;
5890 for (i = 0; i < pixels; i++)
5891 {
5892 /* we computes the coefficient needed to move the scanned value to
5893 the target value */
5894 if (rts88xx_is_color (dev->shadow_regs))
5895 {
5896 /* RED */
5897 dev->shading_coeff[i] = 0;
5898 for (j = yoffset; j < lines; j++)
5899 dev->shading_coeff[i] += data[i + j * bpl];
5900 dev->shading_coeff[i] =
5901 (rtarget / (dev->shading_coeff[i] / (lines - yoffset)));
5902
5903 /* GREEN */
5904 dev->shading_coeff[i + pixels] = 0;
5905 for (j = yoffset; j < lines; j++)
5906 dev->shading_coeff[i + pixels] += data[i + j * bpl + pixels];
5907 dev->shading_coeff[i + pixels] =
5908 ((gtarget / dev->shading_coeff[i + pixels]) * (lines - yoffset));
5909
5910 /* BLUE */
5911 dev->shading_coeff[i + 2 * pixels] = 0;
5912 for (j = yoffset; j < lines; j++)
5913 dev->shading_coeff[i + 2 * pixels] +=
5914 data[i + j * bpl + 2 * pixels];
5915 dev->shading_coeff[i + 2 * pixels] =
5916 ((btarget / dev->shading_coeff[i + 2 * pixels]) *
5917 (lines - yoffset));
5918 }
5919 else
5920 {
5921 dev->shading_coeff[i] = 0;
5922 for (j = yoffset; j < lines; j++)
5923 {
5924 dev->shading_coeff[i] += data[i + j * bpl];
5925 }
5926 dev->shading_coeff[i] =
5927 (rtarget / dev->shading_coeff[i]) * (lines - yoffset);
5928 }
5929 }
5930 free(data);
5931
5932 /* do the scan backward to go back to start position */
5933 regs[0xc6] &= 0xF7;
5934 lines = (8 * 8) / regs[0x7a];
5935 /* it should use linetotal to account for the lineoffset */
5936 if (dev->model.sensor_type == X74_SENSOR)
5937 lines = linetotal;
5938
5939 /* execute scan */
5940 status = low_simple_scan (dev, regs, sx, pixels, 1, lines, &data);
5941 if (status != SANE_STATUS_GOOD)
5942 {
5943 DBG (1,
5944 "sanei_lexmark_low_shading_calibration: low_simple_scan failed!\n");
5945 if(data!=NULL)
5946 free(data);
5947 return status;
5948 }
5949
5950 #ifdef DEEP_DEBUG
5951 write_pnm_file ("shading_bwd.pnm", pixels, lines, rts88xx_is_color (regs),
5952 data);
5953 #endif
5954 free (data);
5955
5956 DBG (2, "sanei_lexmark_low_shading_calibration: end.\n");
5957 return status;
5958 }
5959
5960
5961 SANE_Status
sanei_lexmark_low_calibration(Lexmark_Device * dev)5962 sanei_lexmark_low_calibration (Lexmark_Device * dev)
5963 {
5964 SANE_Status status;
5965
5966 DBG (2, "sanei_lexmark_low_calibration: start.\n");
5967 status = sanei_lexmark_low_offset_calibration (dev);
5968 if (status != SANE_STATUS_GOOD)
5969 return status;
5970
5971 /* we put the offset just computed in scanning regs */
5972 if (rts88xx_is_color (dev->shadow_regs))
5973 {
5974 rts88xx_set_offset (dev->shadow_regs,
5975 dev->offset.red,
5976 dev->offset.green, dev->offset.blue);
5977 }
5978 else
5979 {
5980 rts88xx_set_offset (dev->shadow_regs,
5981 dev->offset.gray,
5982 dev->offset.gray, dev->offset.gray);
5983 }
5984
5985 /* if manual gain settings, no gain calibration */
5986 if (dev->val[OPT_MANUAL_GAIN].w == SANE_TRUE)
5987 {
5988 if (rts88xx_is_color (dev->shadow_regs))
5989 {
5990 dev->gain.red = dev->val[OPT_RED_GAIN].w;
5991 dev->gain.green = dev->val[OPT_GREEN_GAIN].w;
5992 dev->gain.blue = dev->val[OPT_BLUE_GAIN].w;
5993 }
5994 else
5995 dev->gain.gray = dev->val[OPT_GRAY_GAIN].w;
5996 }
5997 else
5998 {
5999 status = sanei_lexmark_low_gain_calibration (dev);
6000 if (status != SANE_STATUS_GOOD)
6001 return status;
6002 }
6003
6004 /* put the calibrated or manual settings before shading calibration
6005 which must be done with final setting values */
6006 if (rts88xx_is_color (dev->shadow_regs))
6007 {
6008 rts88xx_set_gain (dev->shadow_regs, dev->gain.red, dev->gain.green,
6009 dev->gain.blue);
6010 }
6011 else
6012 {
6013 rts88xx_set_gain (dev->shadow_regs, dev->gain.gray, dev->gain.gray,
6014 dev->gain.gray);
6015 }
6016
6017 status = sanei_lexmark_low_shading_calibration (dev);
6018
6019 if (status != SANE_STATUS_GOOD)
6020 return status;
6021
6022 DBG (2, "sanei_lexmark_low_calibration: end.\n");
6023 return SANE_STATUS_GOOD;
6024 }
6025
6026 /* assign sensor data */
6027 static SANE_Status
sanei_lexmark_low_assign_sensor(Lexmark_Device * dev)6028 sanei_lexmark_low_assign_sensor (Lexmark_Device * dev)
6029 {
6030 int dn;
6031
6032 /* init sensor data */
6033 dn = 0;
6034 while (sensor_list[dn].id != 0
6035 && sensor_list[dn].id != dev->model.sensor_type)
6036 dn++;
6037 if (sensor_list[dn].id == 0)
6038 {
6039 DBG (1,
6040 "sanei_lexmark_low_assign_sensor: unknown sensor %d\n",
6041 dev->model.sensor_type);
6042 return SANE_STATUS_UNSUPPORTED;
6043 }
6044 dev->sensor = &(sensor_list[dn]);
6045 DBG (1, "sanei_lexmark_low_assign_sensor: assigned sensor number %d\n",
6046 dev->model.sensor_type);
6047 return SANE_STATUS_GOOD;
6048 }
6049
6050 /* assign model description, based on USB id, and register content when
6051 * available */
6052 SANE_Status
sanei_lexmark_low_assign_model(Lexmark_Device * dev,SANE_String_Const devname,SANE_Int vendor,SANE_Int product,SANE_Byte mainboard)6053 sanei_lexmark_low_assign_model (Lexmark_Device * dev,
6054 SANE_String_Const devname, SANE_Int vendor,
6055 SANE_Int product, SANE_Byte mainboard)
6056 {
6057 int dn;
6058 SANE_Bool found = SANE_FALSE;
6059
6060 DBG_INIT ();
6061
6062 DBG (2, "sanei_lexmark_low_assign_model: start\n");
6063 DBG (3,
6064 "sanei_lexmark_low_assign_model: assigning %04x:%04x, variant %d\n",
6065 vendor, product, mainboard);
6066
6067 dn = 0;
6068 /* walk the list of known devices */
6069 while (!found && model_list[dn].vendor_id != 0)
6070 {
6071 /* no mainboard id given (at attach time) */
6072 if (mainboard == 0
6073 && vendor == model_list[dn].vendor_id
6074 && product == model_list[dn].product_id)
6075 found = SANE_TRUE;
6076 /* mainboard given (init time) */
6077 if (mainboard != 0
6078 && mainboard == model_list[dn].mainboard_id
6079 && vendor == model_list[dn].vendor_id
6080 && product == model_list[dn].product_id)
6081 found = SANE_TRUE;
6082
6083 if (!found)
6084 dn++;
6085 }
6086
6087 /* we hit the end of list, so we don't know about the current model */
6088 if (!found)
6089 {
6090 DBG (1,
6091 "sanei_lexmark_low_assign_model: unknown device 0x%04x:0x%04x\n",
6092 vendor, product);
6093 return SANE_STATUS_UNSUPPORTED;
6094 }
6095
6096 dev->sane.name = strdup (devname);
6097 dev->sane.vendor = model_list[dn].vendor;
6098 dev->sane.model = model_list[dn].model;
6099 dev->model = model_list[dn];
6100 dev->sane.type = "flatbed scanner";
6101
6102 DBG (3, "sanei_lexmark_low_assign_model: assigned %s\n", dev->model.model);
6103
6104 /* init sensor data */
6105 DBG (2, "sanei_lexmark_low_assign_model: end.\n");
6106 return sanei_lexmark_low_assign_sensor (dev);
6107 }
6108