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, &reg);
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, &reg);
903   status = rts88xx_write_reg (devnum, 0xb3, &reg);
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, &reg);
916   rts88xx_write_reg (devnum, 0xb3, &reg);
917   reg = 0x00;
918   rts88xx_write_reg (devnum, 0xb3, &reg);
919   status = rts88xx_write_reg (devnum, 0xb3, &reg);
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, &reg);
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, &reg) != 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