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
56typedef enum
57{
58  black = 0,
59  white
60}
61region_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 */
70static SANE_Status low_usb_bulk_write (SANE_Int devnum,
71				       SANE_Byte * cmd, size_t * size);
72static SANE_Status low_usb_bulk_read (SANE_Int devnum,
73				      SANE_Byte * buf, size_t * size);
74static SANE_Status low_write_all_regs (SANE_Int devnum, SANE_Byte * regs);
75static SANE_Bool low_is_home_line (Lexmark_Device * dev,
76				   unsigned char *buffer);
77static 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);
81static void low_rewind (Lexmark_Device * dev, SANE_Byte * regs);
82static SANE_Status low_start_mvmt (SANE_Int devnum);
83static SANE_Status low_stop_mvmt (SANE_Int devnum);
84static SANE_Status low_clr_c6 (SANE_Int devnum);
85static 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);
91static 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 */
101static SANE_Status read_buffer_init (Lexmark_Device * dev, int bytesperline);
102static SANE_Status read_buffer_free (Read_Buffer * rb);
103static size_t read_buffer_bytes_available (Read_Buffer * rb);
104static SANE_Status read_buffer_add_byte (Read_Buffer * rb,
105					 SANE_Byte * byte_pointer);
106static SANE_Status read_buffer_add_byte_gray (Read_Buffer * rb,
107					      SANE_Byte * byte_pointer);
108static SANE_Status read_buffer_add_bit_lineart (Read_Buffer * rb,
109						SANE_Byte * byte_pointer,
110						SANE_Byte threshold);
111static size_t read_buffer_get_bytes (Read_Buffer * rb, SANE_Byte * buffer,
112				     size_t rqst_size);
113static 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 */
126static SANE_Bool
127rts88xx_is_color (SANE_Byte * regs)
128{
129  if ((regs[0x2f] & 0x11) == 0x11)
130    return SANE_TRUE;
131  return SANE_FALSE;
132}
133
134static void
135rts88xx_set_gray_scan (SANE_Byte * regs)
136{
137  regs[0x2f] = (regs[0x2f] & 0x0f) | 0x20;
138}
139
140#if 0
141static void
142rts88xx_set_color_scan (SANE_Byte * regs)
143{
144  regs[0x2f] = (regs[0x2f] & 0x0f) | 0x10;
145}
146#endif
147
148static void
149rts88xx_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
163static void
164rts88xx_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 */
173static int
174rts88xx_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 */
183static SANE_Status
184rts88xx_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 */
221static SANE_Status
222rts88xx_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 */
261static SANE_Status
262rts88xx_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 */
298static SANE_Status
299rts88xx_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 */
335static SANE_Status
336rts88xx_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 */
370static SANE_Status
371lexmark_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
388static SANE_Status
389lexmark_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
416static void
417write_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 */
458SANE_Status
459sanei_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
839void
840sanei_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
848SANE_Status
849low_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
870SANE_Status
871low_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
895SANE_Status
896low_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
907SANE_Status
908low_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
923SANE_Status
924low_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 */
939static SANE_Status
940low_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
955static SANE_Status
956low_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 */
984static SANE_Status
985low_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 */
1034static SANE_Status
1035low_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 */
1149SANE_Status
1150sanei_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
1241void
1242sanei_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. */
1257SANE_Status
1258low_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
1303SANE_Bool
1304low_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
1463void
1464sanei_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
1647SANE_Bool
1648sanei_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
1945SANE_Bool
1946sanei_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
2309SANE_Status
2310low_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
2400void
2401low_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
2456SANE_Int
2457sanei_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
2863SANE_Status
2864sanei_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
4818SANE_Status
4819sanei_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
4912long
4913sanei_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", (void *) dev->read_pointer);
4998	}
4999    }
5000
5001  DBG (5, "READ BUFFER INFO: \n");
5002  DBG (5, "   write ptr:     %p\n", (void *) dev->read_buffer->writeptr);
5003  DBG (5, "   read ptr:      %p\n", (void *) dev->read_buffer->readptr);
5004  DBG (5, "   max write ptr: %p\n", (void *) 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", (void *) dev->read_buffer->writeptr);
5063  DBG (5, "   read ptr:      %p\n", (void *) dev->read_buffer->readptr);
5064  DBG (5, "   max write ptr: %p\n", (void *) 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", (void *) 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
5100void
5101low_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
5198SANE_Status
5199read_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
5234SANE_Status
5235read_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
5247size_t
5248read_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 (rb->writeptr < rb->readptr)
5256    return (size_t)(rb->readptr - rb->writeptr) < rb->linesize ? 0 :
5257           (size_t)(rb->readptr - rb->writeptr) - rb->linesize;
5258  else
5259    return (size_t)(rb->writeptr - rb->readptr) < rb->linesize ? 0 :
5260           rb->size - (size_t)(rb->writeptr - rb->readptr) - rb->linesize;
5261}
5262
5263SANE_Status
5264read_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
5313SANE_Status
5314read_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
5338SANE_Status
5339read_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
5411size_t
5412read_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
5466SANE_Bool
5467read_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 */
5476static int
5477average_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 */
5522SANE_Status
5523sanei_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 */
5664SANE_Status
5665sanei_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 */
5760SANE_Status
5761sanei_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
5961SANE_Status
5962sanei_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 */
6027static SANE_Status
6028sanei_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 */
6052SANE_Status
6053sanei_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