kopia lustrzana https://gitlab.com/sane-project/backends
				
				
				
			
		
			
				
	
	
		
			5153 wiersze
		
	
	
		
			144 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			5153 wiersze
		
	
	
		
			144 KiB
		
	
	
	
		
			C
		
	
	
/* lexmark-low.c: scanner-interface file for low Lexmark scanners.
 | 
						|
 | 
						|
   (C) 2005 Fred Odendaal
 | 
						|
   (C) 2006-2007 Stéphane Voltz	<stef.dev@free.fr>
 | 
						|
   
 | 
						|
   This file is part of the SANE package.
 | 
						|
 | 
						|
   This program is free software; you can redistribute it and/or
 | 
						|
   modify it under the terms of the GNU General Public License as
 | 
						|
   published by the Free Software Foundation; either version 2 of the
 | 
						|
   License, or (at your option) any later version.
 | 
						|
 | 
						|
   This program is distributed in the hope that it will be useful, but
 | 
						|
   WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
   General Public License for more details.
 | 
						|
 | 
						|
   You should have received a copy of the GNU General Public License
 | 
						|
   along with this program; if not, write to the Free Software
 | 
						|
   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 | 
						|
   MA 02111-1307, USA.
 | 
						|
 | 
						|
   As a special exception, the authors of SANE give permission for
 | 
						|
   additional uses of the libraries contained in this release of SANE.
 | 
						|
 | 
						|
   The exception is that, if you link a SANE library with other files
 | 
						|
   to produce an executable, this does not by itself cause the
 | 
						|
   resulting executable to be covered by the GNU General Public
 | 
						|
   License.  Your use of that executable is in no way restricted on
 | 
						|
   account of linking the SANE library code into it.
 | 
						|
 | 
						|
   This exception does not, however, invalidate any other reasons why
 | 
						|
   the executable file might be covered by the GNU General Public
 | 
						|
   License.
 | 
						|
 | 
						|
   If you submit changes to SANE to the maintainers to be included in
 | 
						|
   a subsequent release, you agree by submitting the changes that
 | 
						|
   those changes may be distributed with this exception intact.
 | 
						|
 | 
						|
   If you write modifications of your own for SANE, it is your choice
 | 
						|
   whether to permit this exception to apply to your modifications.
 | 
						|
   If you do not wish that, delete this exception notice.
 | 
						|
 | 
						|
   **************************************************************************/
 | 
						|
 | 
						|
#include "../include/sane/config.h"
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <math.h>
 | 
						|
 | 
						|
#include "../include/sane/sane.h"
 | 
						|
#include "../include/sane/sanei.h"
 | 
						|
#include "../include/sane/saneopts.h"
 | 
						|
 | 
						|
#include "../include/sane/sanei_usb.h"
 | 
						|
 | 
						|
#include "lexmark.h"
 | 
						|
#include "../include/sane/sanei_backend.h"
 | 
						|
 | 
						|
#include "lexmark_sensors.c"
 | 
						|
#include "lexmark_models.c"
 | 
						|
 | 
						|
/* numbre of ranges for offset */
 | 
						|
#define OFFSET_RANGES 5
 | 
						|
 | 
						|
typedef enum
 | 
						|
{
 | 
						|
  black = 0,
 | 
						|
  white
 | 
						|
}
 | 
						|
region_type;
 | 
						|
 | 
						|
/*
 | 
						|
 * all these defines may be move in device specific constant in per model
 | 
						|
 * struct if we need it
 | 
						|
 */
 | 
						|
#define HomeEdgePoint1 1235
 | 
						|
#define HomeEdgePoint2 1258
 | 
						|
#define HomeTolerance 30
 | 
						|
 | 
						|
#define LOBYTE(x)  ((u_int8_t)((x) & 0xFF))
 | 
						|
#define HIBYTE(x)  ((u_int8_t)((x) >> 8))
 | 
						|
 | 
						|
/* Static low function proto-types */
 | 
						|
static SANE_Status low_usb_bulk_write (SANE_Int devnum,
 | 
						|
					 SANE_Byte * cmd, size_t * size);
 | 
						|
static SANE_Status low_usb_bulk_read (SANE_Int devnum,
 | 
						|
					SANE_Byte * buf, size_t * size);
 | 
						|
static SANE_Status low_write_all_regs (SANE_Int devnum, SANE_Byte * regs);
 | 
						|
static SANE_Bool low_is_home_line (unsigned char *buffer);
 | 
						|
static SANE_Status low_get_start_loc (SANE_Int resolution,
 | 
						|
					SANE_Int * vert_start,
 | 
						|
					SANE_Int * hor_start,
 | 
						|
					SANE_Int offset,
 | 
						|
					Lexmark_Device * dev);
 | 
						|
static void low_rewind (Lexmark_Device * dev, SANE_Byte * regs);
 | 
						|
static SANE_Status low_start_mvmt (SANE_Int devnum);
 | 
						|
static SANE_Status low_stop_mvmt (SANE_Int devnum);
 | 
						|
static SANE_Status low_clr_c6 (SANE_Int devnum);
 | 
						|
static SANE_Status low_simple_scan (Lexmark_Device * dev,
 | 
						|
				      SANE_Byte * regs,
 | 
						|
				      int xoffset,
 | 
						|
				      int pixels,
 | 
						|
				      int yoffset,
 | 
						|
				      int lines, SANE_Byte ** data);
 | 
						|
static void low_set_scan_area (SANE_Int res,
 | 
						|
				 SANE_Int tlx,
 | 
						|
				 SANE_Int tly,
 | 
						|
				 SANE_Int brx,
 | 
						|
				 SANE_Int bry,
 | 
						|
				 SANE_Int offset,
 | 
						|
				 SANE_Bool half_step,
 | 
						|
				 SANE_Byte * regs, Lexmark_Device * dev);
 | 
						|
 | 
						|
/* Static Read Buffer Proto-types */
 | 
						|
static SANE_Status read_buffer_init (Lexmark_Device * dev, int bytesperline);
 | 
						|
static SANE_Status read_buffer_free (Read_Buffer * rb);
 | 
						|
static size_t read_buffer_bytes_available (Read_Buffer * rb);
 | 
						|
static SANE_Status read_buffer_add_byte (Read_Buffer * rb,
 | 
						|
					 SANE_Byte * byte_pointer);
 | 
						|
static SANE_Status read_buffer_add_byte_gray (Read_Buffer * rb,
 | 
						|
					      SANE_Byte * byte_pointer);
 | 
						|
static SANE_Status read_buffer_add_bit_lineart (Read_Buffer * rb,
 | 
						|
						SANE_Byte * byte_pointer,
 | 
						|
						SANE_Byte threshold);
 | 
						|
static size_t read_buffer_get_bytes (Read_Buffer * rb, SANE_Byte * buffer,
 | 
						|
				     size_t rqst_size);
 | 
						|
static SANE_Bool read_buffer_is_empty (Read_Buffer * rb);
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 *         RTS88XX 	START
 | 
						|
 *
 | 
						|
 *         these rts88xx functions will be spin off in a separate lib
 | 
						|
 *         so that they can be reused.
 | 
						|
 */
 | 
						|
 | 
						|
/*
 | 
						|
 * registers helpers to avoid direct access
 | 
						|
 */
 | 
						|
static SANE_Bool
 | 
						|
rts88xx_is_color (SANE_Byte * regs)
 | 
						|
{
 | 
						|
  if ((regs[0x2f] & 0x11) == 0x11)
 | 
						|
    return SANE_TRUE;
 | 
						|
  return SANE_FALSE;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
rts88xx_set_gray_scan (SANE_Byte * regs)
 | 
						|
{
 | 
						|
  regs[0x2f] = (regs[0x2f] & 0x0f) | 0x20;
 | 
						|
}
 | 
						|
 | 
						|
#if 0
 | 
						|
static void
 | 
						|
rts88xx_set_color_scan (SANE_Byte * regs)
 | 
						|
{
 | 
						|
  regs[0x2f] = (regs[0x2f] & 0x0f) | 0x10;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
static void
 | 
						|
rts88xx_set_offset (SANE_Byte * regs, SANE_Byte red, SANE_Byte green,
 | 
						|
		    SANE_Byte blue)
 | 
						|
{
 | 
						|
  /* offset for odd pixels */
 | 
						|
  regs[0x02] = red;
 | 
						|
  regs[0x03] = green;
 | 
						|
  regs[0x04] = blue;
 | 
						|
 | 
						|
  /* offset for even pixels */
 | 
						|
  regs[0x05] = red;
 | 
						|
  regs[0x06] = green;
 | 
						|
  regs[0x07] = blue;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
rts88xx_set_gain (SANE_Byte * regs, SANE_Byte red, SANE_Byte green,
 | 
						|
		  SANE_Byte blue)
 | 
						|
{
 | 
						|
  regs[0x08] = red;
 | 
						|
  regs[0x09] = green;
 | 
						|
  regs[0x0a] = blue;
 | 
						|
}
 | 
						|
 | 
						|
/* set # of head moves per CIS read */
 | 
						|
static int
 | 
						|
rts88xx_set_scan_frequency (SANE_Byte * regs, int frequency)
 | 
						|
{
 | 
						|
  regs[0x64] = (regs[0x64] & 0xf0) | (frequency & 0x0f);
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * read one register at given index 
 | 
						|
 */
 | 
						|
static SANE_Status
 | 
						|
rts88xx_read_reg (SANE_Int devnum, SANE_Int index, SANE_Byte * reg)
 | 
						|
{
 | 
						|
  SANE_Status status = SANE_STATUS_GOOD;
 | 
						|
  unsigned char cmd[] = { 0x80, 0x00, 0x00, 0x01 };
 | 
						|
  size_t size;
 | 
						|
 | 
						|
  cmd[1] = index;
 | 
						|
 | 
						|
  size = 4;
 | 
						|
#ifdef FAKE_USB
 | 
						|
  status = SANE_STATUS_GOOD;
 | 
						|
#else
 | 
						|
  status = sanei_usb_write_bulk (devnum, cmd, &size);
 | 
						|
#endif
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    {
 | 
						|
      DBG (5, "rts88xx_read_reg: bulk write failed\n");
 | 
						|
      return status;
 | 
						|
    }
 | 
						|
  size = 1;
 | 
						|
#ifdef FAKE_USB
 | 
						|
  status = SANE_STATUS_GOOD;
 | 
						|
#else
 | 
						|
  status = sanei_usb_read_bulk (devnum, reg, &size);
 | 
						|
#endif
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    {
 | 
						|
      DBG (5, "rts88xx_read_reg: bulk read failed\n");
 | 
						|
      return status;
 | 
						|
    }
 | 
						|
  DBG (15, "rts88xx_read_reg: reg[0x%02x]=0x%02x\n", index, *reg);
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * write one register at given index 
 | 
						|
 */
 | 
						|
static SANE_Status
 | 
						|
rts88xx_write_reg (SANE_Int devnum, SANE_Int index, SANE_Byte * reg)
 | 
						|
{
 | 
						|
  SANE_Status status = SANE_STATUS_GOOD;
 | 
						|
  unsigned char cmd[] = { 0x88, 0x00, 0x00, 0x01 };
 | 
						|
  size_t size;
 | 
						|
 | 
						|
  cmd[1] = index;
 | 
						|
 | 
						|
  size = 4;
 | 
						|
#ifdef FAKE_USB
 | 
						|
  status = SANE_STATUS_GOOD;
 | 
						|
#else
 | 
						|
  status = sanei_usb_write_bulk (devnum, cmd, &size);
 | 
						|
#endif
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    {
 | 
						|
      DBG (5, "rts88xx_write_reg: bulk write failed\n");
 | 
						|
      return status;
 | 
						|
    }
 | 
						|
  size = 1;
 | 
						|
#ifdef FAKE_USB
 | 
						|
  status = SANE_STATUS_GOOD;
 | 
						|
#else
 | 
						|
  status = sanei_usb_write_bulk (devnum, reg, &size);
 | 
						|
#endif
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    {
 | 
						|
      DBG (5, "rts88xx_write_reg: bulk write failed\n");
 | 
						|
      return status;
 | 
						|
    }
 | 
						|
  DBG (15, "rts88xx_write_reg: reg[0x%02x]=0x%02x\n", index, *reg);
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * write length consecutive registers, starting at index
 | 
						|
 * register 0xb3 is never wrote in bulk register write, so we split
 | 
						|
 * write if it belongs to the register set sent
 | 
						|
 */
 | 
						|
static SANE_Status
 | 
						|
rts88xx_write_regs (SANE_Int devnum, SANE_Int start, SANE_Byte * source,
 | 
						|
		    SANE_Int length)
 | 
						|
{
 | 
						|
  size_t size = 0;
 | 
						|
 | 
						|
  /* when writing several registers at a time, we avoid writing 0xb3
 | 
						|
     register */
 | 
						|
  if ((start + length > 0xb3) && (length > 1))
 | 
						|
    {
 | 
						|
      size = 0xb3 - start;
 | 
						|
      if (low_usb_bulk_write (devnum, source, &size) != SANE_STATUS_GOOD)
 | 
						|
	{
 | 
						|
	  DBG (5, "rts88xx_write_regs : write registers part 1 failed ...\n");
 | 
						|
	  return SANE_STATUS_IO_ERROR;
 | 
						|
	}
 | 
						|
 | 
						|
      /* skip 0xB3 register */
 | 
						|
      size++;
 | 
						|
      start = 0xb4;
 | 
						|
      source = source + size;
 | 
						|
    }
 | 
						|
  size = length - size;
 | 
						|
  if (low_usb_bulk_write (devnum, source, &size) != SANE_STATUS_GOOD)
 | 
						|
    {
 | 
						|
      DBG (5, "rts88xx_write_regs : write registers part 2 failed ...\n");
 | 
						|
      return SANE_STATUS_IO_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * reads 'needed' bytes of scanned data into 'data'. Actual number of bytes get
 | 
						|
 * is retruned in 'size'
 | 
						|
 */
 | 
						|
static SANE_Status
 | 
						|
rts88xx_read_data (SANE_Int devnum, size_t needed, SANE_Byte * data,
 | 
						|
		   size_t * size)
 | 
						|
{
 | 
						|
  SANE_Byte read_cmd[] = { 0x91, 0x00, 0x00, 0x00 };
 | 
						|
  size_t cmd_size;
 | 
						|
  SANE_Status status = SANE_STATUS_GOOD;
 | 
						|
 | 
						|
  /* this block would deserve to be a function */
 | 
						|
  if (needed > MAX_XFER_SIZE)
 | 
						|
    *size = MAX_XFER_SIZE;
 | 
						|
  else
 | 
						|
    *size = needed;
 | 
						|
  read_cmd[3] = (*size) & 0xff;
 | 
						|
  read_cmd[2] = (*size >> 8) & 0xff;
 | 
						|
  read_cmd[1] = (*size >> 16) & 0xff;
 | 
						|
 | 
						|
  /* send header for 'get scanned data' */
 | 
						|
  cmd_size = 4;
 | 
						|
  status = low_usb_bulk_write (devnum, read_cmd, &cmd_size);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    {
 | 
						|
      *size = 0;
 | 
						|
      DBG (5, "rts88xx_read_data : header sending failed ...\n");
 | 
						|
      return status;
 | 
						|
    }
 | 
						|
  /* get actual scanned data */
 | 
						|
  status = low_usb_bulk_read (devnum, data, size);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    {
 | 
						|
      *size = 0;
 | 
						|
      DBG (5, "rts88xx_read_data : data reading failed ...\n");
 | 
						|
    }
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
/* starts scan by sending color depth, stopping head, the starting it */
 | 
						|
static SANE_Status
 | 
						|
rts88xx_commit (SANE_Int devnum, SANE_Byte depth)
 | 
						|
{
 | 
						|
  SANE_Status status;
 | 
						|
  SANE_Byte reg;
 | 
						|
 | 
						|
  DBG (2, "rts88xx_commit: start\n");
 | 
						|
 | 
						|
  /* send color depth depth ??
 | 
						|
   * X1100 -> 0x0f
 | 
						|
   * X1100/B2 -> 0x0d
 | 
						|
   * X1200 -> 0x01 */
 | 
						|
  reg = depth;
 | 
						|
  status = rts88xx_write_reg (devnum, 0x2c, ®);
 | 
						|
 | 
						|
  /* stop before starting */
 | 
						|
  status = low_stop_mvmt (devnum);
 | 
						|
 | 
						|
  /* effective start */
 | 
						|
  status = low_start_mvmt (devnum);
 | 
						|
 | 
						|
  DBG (2, "rts88xx_commit: end\n");
 | 
						|
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 *         RTS88XX     END
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * sets the scanner idle
 | 
						|
 */
 | 
						|
static SANE_Status
 | 
						|
lexmark_low_set_idle (SANE_Int devnum)
 | 
						|
{
 | 
						|
  SANE_Byte regs[14] =
 | 
						|
    { 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
						|
    0x00, 0x60
 | 
						|
  };
 | 
						|
  if (rts88xx_write_regs (devnum, 16, regs, 14) != SANE_STATUS_GOOD)
 | 
						|
    {
 | 
						|
      DBG (5, "lexmark_low_set_idle : register write failed ...\n");
 | 
						|
      return SANE_STATUS_IO_ERROR;
 | 
						|
    }
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* wake up scanner */
 | 
						|
#if 0
 | 
						|
static SANE_Status
 | 
						|
lexmark_low_wake_up (Lexmark_Device * dev)
 | 
						|
{
 | 
						|
  SANE_Byte regs[5] = { 0x12, 0x14, 0x16, 0x18, 0x1a };
 | 
						|
  SANE_Byte values[5] = { 0x0f, 0x00, 0x07, 0x00, 0x00 };
 | 
						|
  int i;
 | 
						|
 | 
						|
  /* send the wake-up sequence, one reg at at time */
 | 
						|
  for (i = 0; i < 10; i++)
 | 
						|
    {
 | 
						|
      if (rts88xx_write_reg (dev->devnum, regs[i], values + i) !=
 | 
						|
	  SANE_STATUS_GOOD)
 | 
						|
	{
 | 
						|
	  DBG (5,
 | 
						|
	       "lexmark_low_wake_up : register write pass %d failed ...\n",
 | 
						|
	       i);
 | 
						|
	  return SANE_STATUS_IO_ERROR;
 | 
						|
	}
 | 
						|
    }
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * 
 | 
						|
 */
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
static void write_pnm_file(char *title, int pixels, int lines, int color, unsigned char *data)
 | 
						|
{
 | 
						|
FILE * fdbg;
 | 
						|
int x,y;
 | 
						|
 | 
						|
 fdbg = fopen (title, "wb");
 | 
						|
 if (fdbg == NULL)
 | 
						|
	 return;
 | 
						|
 | 
						|
 if (color)
 | 
						|
   {
 | 
						|
      fprintf (fdbg, "P6\n%d %d\n255\n", pixels, lines);
 | 
						|
     for (y = 0; y < lines; y++)
 | 
						|
	{
 | 
						|
	  for (x = 0; x < pixels; x += 2)
 | 
						|
	    {
 | 
						|
	      fputc (data[y * pixels * 3 + x + 1], fdbg);
 | 
						|
	      fputc (data[y * pixels * 3 + x + 1 + pixels], fdbg);
 | 
						|
	      fputc (data[y * pixels * 3 + x + 1 + pixels * 2], fdbg);
 | 
						|
	      fputc (data[y * pixels * 3 + x], fdbg);
 | 
						|
	      fputc (data[y * pixels * 3 + x + pixels], fdbg);
 | 
						|
	      fputc (data[y * pixels * 3 + x + pixels * 2], fdbg);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
   }
 | 
						|
 else
 | 
						|
   {
 | 
						|
     fprintf (fdbg, "P5\n%d %d\n255\n", pixels, lines);
 | 
						|
     fwrite (data, pixels, lines, fdbg);
 | 
						|
   }
 | 
						|
 fclose (fdbg);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/*
 | 
						|
 * mid level hardware functions
 | 
						|
 */
 | 
						|
/*
 | 
						|
 * model init
 | 
						|
 */
 | 
						|
SANE_Status
 | 
						|
sanei_lexmark_low_init (Lexmark_Device * dev)
 | 
						|
{
 | 
						|
  int i;
 | 
						|
  SANE_Status status;
 | 
						|
 | 
						|
  DBG_INIT();
 | 
						|
 | 
						|
  status = SANE_STATUS_UNSUPPORTED;
 | 
						|
  DBG (2, "low_init: start\n");
 | 
						|
 | 
						|
  /* clear all registers first */
 | 
						|
  for (i = 0; i < 255; i++)
 | 
						|
    {
 | 
						|
      dev->shadow_regs[i] = 0;
 | 
						|
    }
 | 
						|
 | 
						|
  /* set up per model constant values */
 | 
						|
  switch (dev->model.sensor_type)
 | 
						|
    {
 | 
						|
    case X1100_B2_SENSOR:
 | 
						|
      dev->shadow_regs[0x01] = 0x43;
 | 
						|
      dev->shadow_regs[0x0b] = 0x70;
 | 
						|
      dev->shadow_regs[0x11] = 0x01;
 | 
						|
      dev->shadow_regs[0x12] = 0x0f;
 | 
						|
      dev->shadow_regs[0x13] = 0x01;
 | 
						|
      dev->shadow_regs[0x15] = 0x01;
 | 
						|
      dev->shadow_regs[0x16] = 0x0f;
 | 
						|
      dev->shadow_regs[0x1d] = 0x20;
 | 
						|
      dev->shadow_regs[0x28] = 0xeb;
 | 
						|
      dev->shadow_regs[0x29] = 0xee;
 | 
						|
      dev->shadow_regs[0x2a] = 0xf7;
 | 
						|
      dev->shadow_regs[0x2b] = 0x01;
 | 
						|
      dev->shadow_regs[0x2e] = 0x86;
 | 
						|
      dev->shadow_regs[0x30] = 0x48;
 | 
						|
      dev->shadow_regs[0x33] = 0x01;
 | 
						|
      dev->shadow_regs[0x3a] = 0x20;
 | 
						|
      dev->shadow_regs[0x3b] = 0x37;
 | 
						|
      dev->shadow_regs[0x3c] = 0x88;
 | 
						|
      dev->shadow_regs[0x3d] = 0x08;
 | 
						|
      dev->shadow_regs[0x40] = 0x80;
 | 
						|
      dev->shadow_regs[0x72] = 0x05;
 | 
						|
      dev->shadow_regs[0x74] = 0x0e;
 | 
						|
      dev->shadow_regs[0x8b] = 0xff;
 | 
						|
      dev->shadow_regs[0x8c] = 0x02;
 | 
						|
      dev->shadow_regs[0x8d] = 0x01;
 | 
						|
      dev->shadow_regs[0x8e] = 0x60;
 | 
						|
      dev->shadow_regs[0x8f] = 0x80;
 | 
						|
      dev->shadow_regs[0x94] = 0x0e;
 | 
						|
      dev->shadow_regs[0xa3] = 0xcc;
 | 
						|
      dev->shadow_regs[0xa4] = 0x27;
 | 
						|
      dev->shadow_regs[0xa5] = 0x24;
 | 
						|
      dev->shadow_regs[0xb0] = 0xb2;
 | 
						|
      dev->shadow_regs[0xb2] = 0x04;
 | 
						|
      dev->shadow_regs[0xc2] = 0x80;
 | 
						|
      dev->shadow_regs[0xc4] = 0x20;
 | 
						|
      dev->shadow_regs[0xc8] = 0x04;
 | 
						|
      dev->shadow_regs[0xc9] = 0x3b;
 | 
						|
      dev->shadow_regs[0xed] = 0xc2;
 | 
						|
      dev->shadow_regs[0xee] = 0x02;
 | 
						|
      dev->shadow_regs[0xf3] = 0xf8;
 | 
						|
      dev->shadow_regs[0xf4] = 0x7f;
 | 
						|
      status = SANE_STATUS_GOOD;
 | 
						|
      break;
 | 
						|
    case X1100_2C_SENSOR:
 | 
						|
      dev->shadow_regs[0x00] = 0x00;
 | 
						|
      dev->shadow_regs[0x01] = 0x43;
 | 
						|
      dev->shadow_regs[0x0b] = 0x70;
 | 
						|
      dev->shadow_regs[0x0c] = 0x28;
 | 
						|
      dev->shadow_regs[0x0d] = 0xa4;
 | 
						|
      dev->shadow_regs[0x11] = 0x01;
 | 
						|
      dev->shadow_regs[0x12] = 0x0f;
 | 
						|
      dev->shadow_regs[0x13] = 0x01;
 | 
						|
      dev->shadow_regs[0x15] = 0x01;
 | 
						|
      dev->shadow_regs[0x16] = 0x0f;
 | 
						|
      dev->shadow_regs[0x17] = 0x00;
 | 
						|
      dev->shadow_regs[0x1d] = 0x20;
 | 
						|
      dev->shadow_regs[0x28] = 0xf5;
 | 
						|
      dev->shadow_regs[0x29] = 0xf7;
 | 
						|
      dev->shadow_regs[0x2a] = 0xf5;
 | 
						|
      dev->shadow_regs[0x2b] = 0x17;
 | 
						|
      dev->shadow_regs[0x2d] = 0x41;
 | 
						|
      dev->shadow_regs[0x2e] = 0x86;
 | 
						|
      dev->shadow_regs[0x2f] = 0x11;
 | 
						|
      dev->shadow_regs[0x30] = 0x48;
 | 
						|
      dev->shadow_regs[0x31] = 0x01;
 | 
						|
      dev->shadow_regs[0x33] = 0x01;
 | 
						|
      dev->shadow_regs[0x34] = 0x50;
 | 
						|
      dev->shadow_regs[0x35] = 0x01;
 | 
						|
      dev->shadow_regs[0x36] = 0x50;
 | 
						|
      dev->shadow_regs[0x37] = 0x01;
 | 
						|
      dev->shadow_regs[0x38] = 0x50;
 | 
						|
      dev->shadow_regs[0x3a] = 0x20;
 | 
						|
      dev->shadow_regs[0x3b] = 0x37;
 | 
						|
      dev->shadow_regs[0x3c] = 0x88;
 | 
						|
      dev->shadow_regs[0x3d] = 0x08;
 | 
						|
      dev->shadow_regs[0x40] = 0x80;
 | 
						|
      dev->shadow_regs[0x47] = 0x01;
 | 
						|
      dev->shadow_regs[0x48] = 0x1a;
 | 
						|
      dev->shadow_regs[0x49] = 0x5b;
 | 
						|
      dev->shadow_regs[0x4a] = 0x1b;
 | 
						|
      dev->shadow_regs[0x4b] = 0x5b;
 | 
						|
      dev->shadow_regs[0x4c] = 0x05;
 | 
						|
      dev->shadow_regs[0x4d] = 0x3f;
 | 
						|
      dev->shadow_regs[0x60] = 0x2f;
 | 
						|
      dev->shadow_regs[0x61] = 0x36;
 | 
						|
      dev->shadow_regs[0x62] = 0x30;
 | 
						|
      dev->shadow_regs[0x63] = 0x36;
 | 
						|
      dev->shadow_regs[0x65] = 0x80;
 | 
						|
      dev->shadow_regs[0x66] = 0x64;
 | 
						|
      dev->shadow_regs[0x6c] = 0xc8;
 | 
						|
      dev->shadow_regs[0x6d] = 0x00;
 | 
						|
      dev->shadow_regs[0x72] = 0x35;
 | 
						|
      dev->shadow_regs[0x74] = 0x4e;
 | 
						|
      dev->shadow_regs[0x75] = 0x03;
 | 
						|
      dev->shadow_regs[0x79] = 0x40;
 | 
						|
      dev->shadow_regs[0x7a] = 0x01;
 | 
						|
      dev->shadow_regs[0x85] = 0x02;
 | 
						|
      dev->shadow_regs[0x86] = 0x33;
 | 
						|
      dev->shadow_regs[0x87] = 0x0f;
 | 
						|
      dev->shadow_regs[0x88] = 0x24;
 | 
						|
      dev->shadow_regs[0x8b] = 0xff;
 | 
						|
      dev->shadow_regs[0x8c] = 0x02;
 | 
						|
      dev->shadow_regs[0x8d] = 0x01;
 | 
						|
      dev->shadow_regs[0x8e] = 0x60;
 | 
						|
      dev->shadow_regs[0x8f] = 0x80;
 | 
						|
      dev->shadow_regs[0x91] = 0x19;
 | 
						|
      dev->shadow_regs[0x92] = 0x20;
 | 
						|
      dev->shadow_regs[0x93] = 0x02;
 | 
						|
      dev->shadow_regs[0x94] = 0x0e;
 | 
						|
      dev->shadow_regs[0xa3] = 0x0d;
 | 
						|
      dev->shadow_regs[0xa4] = 0x5e;
 | 
						|
      dev->shadow_regs[0xa5] = 0x23;
 | 
						|
      dev->shadow_regs[0xb0] = 0x2c;
 | 
						|
      dev->shadow_regs[0xb1] = 0x07;
 | 
						|
      dev->shadow_regs[0xb2] = 0x04;
 | 
						|
      dev->shadow_regs[0xc2] = 0x80;
 | 
						|
      dev->shadow_regs[0xc3] = 0x01;
 | 
						|
      dev->shadow_regs[0xc4] = 0x20;
 | 
						|
      dev->shadow_regs[0xc5] = 0x0a;
 | 
						|
      dev->shadow_regs[0xc8] = 0x04;
 | 
						|
      dev->shadow_regs[0xc9] = 0x3b;
 | 
						|
      dev->shadow_regs[0xca] = 0x0a;
 | 
						|
      dev->shadow_regs[0xe2] = 0xf8;
 | 
						|
      dev->shadow_regs[0xe3] = 0x2a;
 | 
						|
      dev->shadow_regs[0xf3] = 0xf8;
 | 
						|
      dev->shadow_regs[0xf4] = 0x7f;
 | 
						|
      status = SANE_STATUS_GOOD;
 | 
						|
      break;
 | 
						|
    case X1200_USB2_SENSOR:
 | 
						|
      dev->shadow_regs[0x01] = 0x43;
 | 
						|
      dev->shadow_regs[0x11] = 0x01;
 | 
						|
      dev->shadow_regs[0x12] = 0x0f;
 | 
						|
      dev->shadow_regs[0x13] = 0x01;
 | 
						|
      dev->shadow_regs[0x15] = 0x01;
 | 
						|
      dev->shadow_regs[0x16] = 0x0f;
 | 
						|
      dev->shadow_regs[0x17] = 0x00;
 | 
						|
      dev->shadow_regs[0x1d] = 0x20;
 | 
						|
      dev->shadow_regs[0x28] = 0xf5;
 | 
						|
      dev->shadow_regs[0x29] = 0xf7;
 | 
						|
      dev->shadow_regs[0x2a] = 0xf5;
 | 
						|
      dev->shadow_regs[0x2b] = 0x17;
 | 
						|
      dev->shadow_regs[0x2d] = 0x41;
 | 
						|
      dev->shadow_regs[0x2e] = 0x86;
 | 
						|
      dev->shadow_regs[0x30] = 0x48;
 | 
						|
      dev->shadow_regs[0x31] = 0x01;
 | 
						|
      dev->shadow_regs[0x33] = 0x01;
 | 
						|
      dev->shadow_regs[0x34] = 0x50;
 | 
						|
      dev->shadow_regs[0x35] = 0x01;
 | 
						|
      dev->shadow_regs[0x36] = 0x50;
 | 
						|
      dev->shadow_regs[0x37] = 0x01;
 | 
						|
      dev->shadow_regs[0x38] = 0x50;
 | 
						|
      dev->shadow_regs[0x3c] = 0x88;
 | 
						|
      dev->shadow_regs[0x3d] = 0x08;
 | 
						|
      dev->shadow_regs[0x66] = 0x64;
 | 
						|
      dev->shadow_regs[0x67] = 0x00;
 | 
						|
      dev->shadow_regs[0x6c] = 0xc8;
 | 
						|
      dev->shadow_regs[0x6d] = 0x00;
 | 
						|
      dev->shadow_regs[0x72] = 0x35;
 | 
						|
      dev->shadow_regs[0x74] = 0x4e;
 | 
						|
      dev->shadow_regs[0x75] = 0x03;
 | 
						|
      dev->shadow_regs[0x7a] = 0x01;
 | 
						|
      dev->shadow_regs[0x93] = 0x0a;
 | 
						|
      dev->shadow_regs[0x94] = 0x0e;
 | 
						|
 | 
						|
      dev->shadow_regs[0xc3] = 0x01;
 | 
						|
      dev->shadow_regs[0xc4] = 0x20;
 | 
						|
      dev->shadow_regs[0xc5] = 0x0a;
 | 
						|
      dev->shadow_regs[0xc8] = 0x04;
 | 
						|
      dev->shadow_regs[0xc9] = 0x3b;
 | 
						|
      dev->shadow_regs[0xca] = 0x0a;
 | 
						|
      dev->shadow_regs[0xe2] = 0xf8;
 | 
						|
      dev->shadow_regs[0xe3] = 0x2a;
 | 
						|
      dev->shadow_regs[0xf3] = 0xf8;
 | 
						|
      dev->shadow_regs[0xf4] = 0x7f;
 | 
						|
      status = SANE_STATUS_GOOD;
 | 
						|
      break;
 | 
						|
    case A920_SENSOR:
 | 
						|
      dev->shadow_regs[0x01] = 0x43;
 | 
						|
      dev->shadow_regs[0x0b] = 0x70;
 | 
						|
      dev->shadow_regs[0x0c] = 0x28;
 | 
						|
      dev->shadow_regs[0x0d] = 0xa4;
 | 
						|
      dev->shadow_regs[0x11] = 0x01;
 | 
						|
      dev->shadow_regs[0x12] = 0x0f;
 | 
						|
      dev->shadow_regs[0x13] = 0x01;
 | 
						|
      dev->shadow_regs[0x15] = 0x01;
 | 
						|
      dev->shadow_regs[0x16] = 0x07;
 | 
						|
      dev->shadow_regs[0x1d] = 0x20;
 | 
						|
      dev->shadow_regs[0x28] = 0xf5;
 | 
						|
      dev->shadow_regs[0x29] = 0xf7;
 | 
						|
      dev->shadow_regs[0x2a] = 0xf5;
 | 
						|
      dev->shadow_regs[0x2b] = 0x17;
 | 
						|
      dev->shadow_regs[0x2e] = 0x86;
 | 
						|
      dev->shadow_regs[0x30] = 0x48;
 | 
						|
      dev->shadow_regs[0x31] = 0x01;
 | 
						|
      dev->shadow_regs[0x33] = 0x01;
 | 
						|
      dev->shadow_regs[0x3a] = 0x20;
 | 
						|
      dev->shadow_regs[0x3b] = 0x37;
 | 
						|
      dev->shadow_regs[0x3c] = 0x88;
 | 
						|
      dev->shadow_regs[0x3d] = 0x08;
 | 
						|
      dev->shadow_regs[0x47] = 0x21;
 | 
						|
      dev->shadow_regs[0x48] = 0x1a;
 | 
						|
      dev->shadow_regs[0x49] = 0x5b;
 | 
						|
      dev->shadow_regs[0x4a] = 0x1b;
 | 
						|
      dev->shadow_regs[0x4b] = 0x5b;
 | 
						|
      dev->shadow_regs[0x4c] = 0x05;
 | 
						|
      dev->shadow_regs[0x4d] = 0x3f;
 | 
						|
      dev->shadow_regs[0x65] = 0x80;
 | 
						|
      dev->shadow_regs[0x86] = 0x14;
 | 
						|
      dev->shadow_regs[0x87] = 0x06;
 | 
						|
      dev->shadow_regs[0x89] = 0xf5;
 | 
						|
      dev->shadow_regs[0x8d] = 0x01;
 | 
						|
      dev->shadow_regs[0x8e] = 0x60;
 | 
						|
      dev->shadow_regs[0x8f] = 0x80;
 | 
						|
      dev->shadow_regs[0x94] = 0x0e;
 | 
						|
      dev->shadow_regs[0xa3] = 0x0d;
 | 
						|
      dev->shadow_regs[0xa4] = 0x5e;
 | 
						|
      dev->shadow_regs[0xa5] = 0x23;
 | 
						|
      dev->shadow_regs[0xb0] = 0x2c;
 | 
						|
      dev->shadow_regs[0xb1] = 0x0f;
 | 
						|
      dev->shadow_regs[0xc2] = 0x80;
 | 
						|
      dev->shadow_regs[0xc4] = 0x20;
 | 
						|
      dev->shadow_regs[0xc8] = 0x04;
 | 
						|
      dev->shadow_regs[0xf3] = 0xf8;
 | 
						|
      dev->shadow_regs[0xf4] = 0x7f;
 | 
						|
      status = SANE_STATUS_GOOD;
 | 
						|
      break;
 | 
						|
    case X1200_SENSOR:
 | 
						|
      dev->shadow_regs[0x01] = 0x43;
 | 
						|
      dev->shadow_regs[0x0b] = 0x70;
 | 
						|
      dev->shadow_regs[0x0c] = 0x28;
 | 
						|
      dev->shadow_regs[0x0d] = 0xa4;
 | 
						|
      dev->shadow_regs[0x11] = 0x01;
 | 
						|
      dev->shadow_regs[0x12] = 0x0f;
 | 
						|
      dev->shadow_regs[0x13] = 0x01;
 | 
						|
      dev->shadow_regs[0x15] = 0x01;
 | 
						|
      dev->shadow_regs[0x16] = 0x0f;
 | 
						|
      dev->shadow_regs[0x1d] = 0x20;
 | 
						|
      dev->shadow_regs[0x28] = 0xe9;
 | 
						|
      dev->shadow_regs[0x29] = 0xeb;
 | 
						|
      dev->shadow_regs[0x2a] = 0xe9;
 | 
						|
      dev->shadow_regs[0x2b] = 0x0b;
 | 
						|
      dev->shadow_regs[0x2d] = 0x01;
 | 
						|
      dev->shadow_regs[0x2e] = 0x86;
 | 
						|
      dev->shadow_regs[0x2f] = 0x11;
 | 
						|
      dev->shadow_regs[0x30] = 0x48;
 | 
						|
      dev->shadow_regs[0x33] = 0x01;
 | 
						|
      dev->shadow_regs[0x34] = 0x50;
 | 
						|
      dev->shadow_regs[0x35] = 0x01;
 | 
						|
      dev->shadow_regs[0x36] = 0x50;
 | 
						|
      dev->shadow_regs[0x37] = 0x01;
 | 
						|
      dev->shadow_regs[0x38] = 0x50;
 | 
						|
      dev->shadow_regs[0x3a] = 0x20;
 | 
						|
      dev->shadow_regs[0x3b] = 0x37;
 | 
						|
      dev->shadow_regs[0x3c] = 0x88;
 | 
						|
      dev->shadow_regs[0x3d] = 0x08;
 | 
						|
      dev->shadow_regs[0x40] = 0x80;
 | 
						|
      dev->shadow_regs[0x47] = 0x01;
 | 
						|
      dev->shadow_regs[0x48] = 0x1a;
 | 
						|
      dev->shadow_regs[0x49] = 0x5b;
 | 
						|
      dev->shadow_regs[0x4a] = 0x1b;
 | 
						|
      dev->shadow_regs[0x4b] = 0x5b;
 | 
						|
      dev->shadow_regs[0x4c] = 0x05;
 | 
						|
      dev->shadow_regs[0x4d] = 0x3f;
 | 
						|
      dev->shadow_regs[0x60] = 0x12;
 | 
						|
      dev->shadow_regs[0x62] = 0x81;
 | 
						|
      dev->shadow_regs[0x63] = 0x03;
 | 
						|
      dev->shadow_regs[0x65] = 0x80;
 | 
						|
      dev->shadow_regs[0x66] = 0x64;
 | 
						|
      dev->shadow_regs[0x6c] = 0xc8;
 | 
						|
      dev->shadow_regs[0x72] = 0x1e;
 | 
						|
      dev->shadow_regs[0x74] = 0x3c;
 | 
						|
      dev->shadow_regs[0x75] = 0x03;
 | 
						|
      dev->shadow_regs[0x79] = 0x40;
 | 
						|
      dev->shadow_regs[0x7a] = 0x01;
 | 
						|
      dev->shadow_regs[0x85] = 0x20;
 | 
						|
      dev->shadow_regs[0x86] = 0x1e;
 | 
						|
      dev->shadow_regs[0x87] = 0x39;
 | 
						|
      dev->shadow_regs[0x8b] = 0xff;
 | 
						|
      dev->shadow_regs[0x8c] = 0x02;
 | 
						|
      dev->shadow_regs[0x8d] = 0x01;
 | 
						|
      dev->shadow_regs[0x8e] = 0x60;
 | 
						|
      dev->shadow_regs[0x8f] = 0x80;
 | 
						|
      dev->shadow_regs[0x92] = 0x92;
 | 
						|
      dev->shadow_regs[0x93] = 0x02;
 | 
						|
      dev->shadow_regs[0x94] = 0x0e;
 | 
						|
      dev->shadow_regs[0xa3] = 0x0d;
 | 
						|
      dev->shadow_regs[0xa4] = 0x5e;
 | 
						|
      dev->shadow_regs[0xa5] = 0x23;
 | 
						|
      dev->shadow_regs[0xb0] = 0x2c;
 | 
						|
      dev->shadow_regs[0xb1] = 0x07;
 | 
						|
      dev->shadow_regs[0xb2] = 0x04;
 | 
						|
      dev->shadow_regs[0xc2] = 0x80;
 | 
						|
      dev->shadow_regs[0xc3] = 0x01;
 | 
						|
      dev->shadow_regs[0xc4] = 0x20;
 | 
						|
      dev->shadow_regs[0xc5] = 0x0a;
 | 
						|
      dev->shadow_regs[0xc8] = 0x04;
 | 
						|
      dev->shadow_regs[0xc9] = 0x3b;
 | 
						|
      dev->shadow_regs[0xca] = 0x0a;
 | 
						|
      dev->shadow_regs[0xe2] = 0xf8;
 | 
						|
      dev->shadow_regs[0xe3] = 0x2a;
 | 
						|
      dev->shadow_regs[0xf3] = 0xff;
 | 
						|
      dev->shadow_regs[0xf4] = 0x0f;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  DBG (5, "sanei_lexmark_low_init: init done for model %s/%s\n",
 | 
						|
       dev->model.model, dev->model.name);
 | 
						|
  DBG (2, "low_init: done\n");
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
sanei_lexmark_low_destroy (Lexmark_Device * dev)
 | 
						|
{
 | 
						|
  /* free the read buffer */
 | 
						|
  if (dev->read_buffer != NULL)
 | 
						|
    read_buffer_free (dev->read_buffer);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
SANE_Status
 | 
						|
low_usb_bulk_write (SANE_Int devnum, SANE_Byte * cmd, size_t * size)
 | 
						|
{
 | 
						|
  SANE_Status status;
 | 
						|
  size_t cmd_size;
 | 
						|
 | 
						|
  cmd_size = *size;
 | 
						|
#ifdef FAKE_USB
 | 
						|
  status = SANE_STATUS_GOOD;
 | 
						|
#else
 | 
						|
  status = sanei_usb_write_bulk (devnum, cmd, size);
 | 
						|
#endif
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    {
 | 
						|
      DBG (5,
 | 
						|
	   "low_usb_bulk_write: returned %s (size = %ld, expected %d)\n",
 | 
						|
	   sane_strstatus (status), (long int) *size, cmd_size);
 | 
						|
      /* F.O. should reset the pipe here... */
 | 
						|
    }
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
SANE_Status
 | 
						|
low_usb_bulk_read (SANE_Int devnum, SANE_Byte * buf, size_t * size)
 | 
						|
{
 | 
						|
  SANE_Status status;
 | 
						|
  size_t exp_size;
 | 
						|
 | 
						|
  exp_size = *size;
 | 
						|
#ifdef FAKE_USB
 | 
						|
  status = SANE_STATUS_GOOD;
 | 
						|
#else
 | 
						|
  status = sanei_usb_read_bulk (devnum, buf, size);
 | 
						|
#endif
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    {
 | 
						|
      DBG (5,
 | 
						|
	   "low_usb_bulk_read: returned %s (size = %ld, expected %d)\n",
 | 
						|
	   sane_strstatus (status), (long int) *size, exp_size);
 | 
						|
      /* F.O. should reset the pipe here... */
 | 
						|
    }
 | 
						|
  DBG (7, "low_usb_bulk_read: returned size = %ld (required %d)\n",
 | 
						|
       (long int) *size, exp_size);
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
SANE_Status
 | 
						|
low_start_mvmt (SANE_Int devnum)
 | 
						|
{
 | 
						|
  SANE_Status status;
 | 
						|
  SANE_Byte reg;
 | 
						|
 | 
						|
  reg = 0x68;
 | 
						|
  status = rts88xx_write_reg (devnum, 0xb3, ®);
 | 
						|
  status = rts88xx_write_reg (devnum, 0xb3, ®);
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
SANE_Status
 | 
						|
low_stop_mvmt (SANE_Int devnum)
 | 
						|
{
 | 
						|
  SANE_Status status;
 | 
						|
  SANE_Byte reg;
 | 
						|
 | 
						|
  /* Stop scanner - clear reg 0xb3: */
 | 
						|
  reg = 0x02;
 | 
						|
  status = rts88xx_write_reg (devnum, 0xb3, ®);
 | 
						|
  status = rts88xx_write_reg (devnum, 0xb3, ®);
 | 
						|
  reg = 0x00;
 | 
						|
  status = rts88xx_write_reg (devnum, 0xb3, ®);
 | 
						|
  status = rts88xx_write_reg (devnum, 0xb3, ®);
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
SANE_Status
 | 
						|
low_clr_c6 (SANE_Int devnum)
 | 
						|
{
 | 
						|
  SANE_Status status;
 | 
						|
  SANE_Byte reg;
 | 
						|
 | 
						|
  /* Clear register 0xC6 */
 | 
						|
  /* cmd_size = 0x05;
 | 
						|
  return low_usb_bulk_write (devnum, clearC6_command_block, &cmd_size);*/
 | 
						|
  
 | 
						|
  reg = 0x00;
 | 
						|
  status = rts88xx_write_reg (devnum, 0xc6, ®);
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
/* stops current scan */
 | 
						|
static SANE_Status
 | 
						|
low_cancel (SANE_Int devnum)
 | 
						|
{
 | 
						|
  SANE_Status status;
 | 
						|
 | 
						|
  DBG (2, "low_cancel: start\n");
 | 
						|
  status = low_stop_mvmt (devnum);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    return status;
 | 
						|
  status = low_clr_c6 (devnum);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    return status;
 | 
						|
  DBG (2, "low_cancel: end.\n");
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
static SANE_Status
 | 
						|
low_start_scan (SANE_Int devnum, SANE_Byte * regs)
 | 
						|
{
 | 
						|
  SANE_Status status;
 | 
						|
 | 
						|
  DBG (2, "low_start_scan: start\n");
 | 
						|
 | 
						|
  /* writes registers to scanner */
 | 
						|
  regs[0x32] = 0x00;
 | 
						|
  status = low_write_all_regs (devnum, regs);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    return status;
 | 
						|
  regs[0x32] = 0x40;
 | 
						|
  status = low_write_all_regs (devnum, regs);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    return status;
 | 
						|
 | 
						|
  /* Stop scanner - clear reg 0xb3: */
 | 
						|
  /* status = low_stop_mvmt (devnum);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    return status; */
 | 
						|
 | 
						|
  /* then start */
 | 
						|
  status = rts88xx_commit (devnum, regs[0x2c]);
 | 
						|
  DBG (2, "low_start_scan: end.\n");
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
/* wait for scan data being available */
 | 
						|
static SANE_Status
 | 
						|
low_poll_data (SANE_Int devnum)
 | 
						|
{
 | 
						|
  SANE_Status status;
 | 
						|
  int loops = 0;
 | 
						|
  size_t size;
 | 
						|
  static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 };
 | 
						|
  SANE_Byte result[3];
 | 
						|
  SANE_Word count;
 | 
						|
 | 
						|
  /* Poll the available byte count until not 0 */
 | 
						|
  while (loops < 1000)
 | 
						|
    {
 | 
						|
      /* 10 ms sleep */
 | 
						|
      usleep (10000);
 | 
						|
 | 
						|
      /* as stated in sanei_lexmark_low_search_home_bwd, we read
 | 
						|
       * available data count twice */
 | 
						|
      size = 4;
 | 
						|
      status = low_usb_bulk_write (devnum, command4_block, &size);
 | 
						|
      if (status != SANE_STATUS_GOOD)
 | 
						|
	return status;
 | 
						|
      size = 0x3;
 | 
						|
      status = low_usb_bulk_read (devnum, result, &size);
 | 
						|
      if (status != SANE_STATUS_GOOD)
 | 
						|
	return status;
 | 
						|
      size = 4;
 | 
						|
      /* read availbale data size again */
 | 
						|
      status = low_usb_bulk_write (devnum, command4_block, &size);
 | 
						|
      if (status != SANE_STATUS_GOOD)
 | 
						|
	return status;
 | 
						|
      size = 0x3;
 | 
						|
      status = low_usb_bulk_read (devnum, result, &size);
 | 
						|
      if (status != SANE_STATUS_GOOD)
 | 
						|
	return status;
 | 
						|
      count = result[0] + (result[1] << 8) + (result[2] << 16);
 | 
						|
      if (count != 0)
 | 
						|
	{
 | 
						|
	  DBG (15, "low_poll_data: %d bytes available\n", count);
 | 
						|
	  return SANE_STATUS_GOOD;
 | 
						|
	}
 | 
						|
      loops++;
 | 
						|
    }
 | 
						|
  return SANE_STATUS_IO_ERROR;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * do a simple scan with the given registers. data buffer is allocated within
 | 
						|
 * the function
 | 
						|
 */
 | 
						|
static SANE_Status
 | 
						|
low_simple_scan (Lexmark_Device * dev, SANE_Byte * regs, int xoffset,
 | 
						|
		   int pixels, int yoffset, int lines, SANE_Byte ** data)
 | 
						|
{
 | 
						|
  SANE_Status status = SANE_STATUS_GOOD;
 | 
						|
  static SANE_Byte reg;
 | 
						|
  size_t size, read, needed;
 | 
						|
  int i, bpl, yend;
 | 
						|
 | 
						|
  DBG (2, "low_simple_scan: start\n");
 | 
						|
  DBG (15, "low_simple_scan: x=%d, pixels=%d (ex=%d), y=%d, lines=%d\n",
 | 
						|
       xoffset, pixels, xoffset + pixels * regs[0x7a], yoffset, lines);
 | 
						|
 | 
						|
  /* set up registers */
 | 
						|
  regs[0x60] = LOBYTE (yoffset);
 | 
						|
  regs[0x61] = HIBYTE (yoffset);
 | 
						|
  yend = yoffset + lines;
 | 
						|
  if (dev->model.motor_type == A920_MOTOR && rts88xx_is_color (regs)
 | 
						|
      && dev->val[OPT_RESOLUTION].w == 600)
 | 
						|
    yend *= 2;
 | 
						|
  regs[0x62] = LOBYTE (yend);
 | 
						|
  regs[0x63] = HIBYTE (yend);
 | 
						|
 | 
						|
  regs[0x66] = LOBYTE (xoffset);
 | 
						|
  regs[0x67] = HIBYTE (xoffset);
 | 
						|
 | 
						|
  regs[0x6c] = LOBYTE (xoffset + pixels * regs[0x7a]);
 | 
						|
  regs[0x6d] = HIBYTE (xoffset + pixels * regs[0x7a]);
 | 
						|
 | 
						|
  /* allocate memory */
 | 
						|
  if (rts88xx_is_color (regs))
 | 
						|
    bpl = 3 * pixels;
 | 
						|
  else
 | 
						|
    bpl = pixels;
 | 
						|
  *data = (SANE_Byte *) malloc (bpl * lines);
 | 
						|
  if (*data == NULL)
 | 
						|
    {
 | 
						|
      DBG (2,
 | 
						|
	   "low_simple_scan: failed to allocate %d bytes !\n", bpl * lines);
 | 
						|
      return SANE_STATUS_NO_MEM;
 | 
						|
    }
 | 
						|
 | 
						|
  /* start scan */
 | 
						|
  status = low_cancel (dev->devnum);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    return status;
 | 
						|
 | 
						|
 | 
						|
  status = low_start_scan (dev->devnum, regs);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    return status;
 | 
						|
 | 
						|
  /* wait for data */
 | 
						|
  status = low_poll_data (dev->devnum);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    {
 | 
						|
      DBG (1, "low_simple_scan: time-out while waiting for data.\n");
 | 
						|
      return status;
 | 
						|
    }
 | 
						|
 | 
						|
  /* data reading loop */
 | 
						|
  needed = bpl * lines;
 | 
						|
  DBG (1, "low_simple_scan: bpl=%d, lines=%d, needed=%d.\n", bpl, lines,
 | 
						|
       needed);
 | 
						|
  read = 0;
 | 
						|
  do
 | 
						|
    {
 | 
						|
      /* this block would deserve to be a function */
 | 
						|
      status =
 | 
						|
	rts88xx_read_data (dev->devnum, needed - read, (*data) + read, &size);
 | 
						|
      if (status != SANE_STATUS_GOOD)
 | 
						|
	return status;
 | 
						|
      read += size;
 | 
						|
    }
 | 
						|
  while (read < needed);
 | 
						|
 | 
						|
  /* if needed, wait for motor to stop */
 | 
						|
  if (regs[0xc3] & 0x80)
 | 
						|
    {
 | 
						|
      i = 0;
 | 
						|
      do
 | 
						|
	{
 | 
						|
	  if (rts88xx_read_reg (dev->devnum, 0xb3, ®) != SANE_STATUS_GOOD)
 | 
						|
	    {
 | 
						|
	      DBG (5, "low_simple_scan: register read failed ...\n");
 | 
						|
	      return SANE_STATUS_IO_ERROR;
 | 
						|
	    }
 | 
						|
	  usleep (100000);
 | 
						|
	  i++;
 | 
						|
	}
 | 
						|
      while ((reg & 0x08) && (i < 100));
 | 
						|
      if (reg & 0x08)
 | 
						|
	{
 | 
						|
	  DBG (5,
 | 
						|
	       "low_simple_scan : timeout waiting for motor to stop ...\n");
 | 
						|
	  return SANE_STATUS_IO_ERROR;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  /* stop scan */
 | 
						|
  status = low_cancel (dev->devnum);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    {
 | 
						|
      DBG (1, "low_simple_scan: cancel failed.\n");
 | 
						|
      return status;
 | 
						|
    }
 | 
						|
 | 
						|
  DBG (2, "low_simple_scan: end.\n");
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * open USB device ,read initial registers values and probe sensor
 | 
						|
 */
 | 
						|
SANE_Status
 | 
						|
sanei_lexmark_low_open_device (Lexmark_Device * dev)
 | 
						|
{
 | 
						|
  /* This function calls the Sane Interface to open this usb device.
 | 
						|
     It also needlessly does what the Windows driver does and reads
 | 
						|
     the entire register set - this may be removed. */
 | 
						|
 | 
						|
  SANE_Status result;
 | 
						|
  static SANE_Byte command_block[] = { 0x80, 0, 0x00, 0xFF };
 | 
						|
  size_t size;
 | 
						|
  SANE_Byte variant = 0;
 | 
						|
  SANE_Byte shadow_regs[255];
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
  int i;
 | 
						|
#endif
 | 
						|
  int sx, ex;
 | 
						|
  int sy, ey;
 | 
						|
 | 
						|
 | 
						|
#ifdef FAKE_USB
 | 
						|
  result = SANE_STATUS_GOOD;
 | 
						|
  shadow_regs[0x00] = 0x91;
 | 
						|
  shadow_regs[0xb0] = 0x2c;
 | 
						|
  shadow_regs[0x10] = 0x97;
 | 
						|
  shadow_regs[0x10] = 0x87;
 | 
						|
  shadow_regs[0xf3] = 0xf8;
 | 
						|
  shadow_regs[0xf4] = 0x7f;
 | 
						|
#else
 | 
						|
  result = sanei_usb_open (dev->sane.name, &(dev->devnum));
 | 
						|
#endif
 | 
						|
  DBG (2, "sanei_lexmark_low_open_device: devnum=%d\n", dev->devnum);
 | 
						|
 | 
						|
  size = 4;
 | 
						|
  low_usb_bulk_write (dev->devnum, command_block, &size);
 | 
						|
  size = 0xFF;
 | 
						|
  low_usb_bulk_read (dev->devnum, shadow_regs, &size);
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
  if (DBG_LEVEL > 2)
 | 
						|
    {
 | 
						|
      fprintf (stderr,
 | 
						|
	       "sanei_lexmark_low_open_device: initial registers values\n");
 | 
						|
      fprintf (stderr, "read_all(0x00,255)=");
 | 
						|
      for (i = 0; i < 255; i++)
 | 
						|
	{
 | 
						|
	  fprintf (stderr, "0x%02x ", shadow_regs[i]);
 | 
						|
	}
 | 
						|
      fprintf (stderr, "\n");
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
  /* it seems that at first read after reset, registers hold information
 | 
						|
   * about the scanner. Register 0x00 is overwritten with 0, so only first read
 | 
						|
   * after USB plug-in gives this value */
 | 
						|
  if (shadow_regs[0] == 0x91)
 | 
						|
    {
 | 
						|
      sx = shadow_regs[0x67] * 256 + shadow_regs[0x66];
 | 
						|
      ex = shadow_regs[0x6d] * 256 + shadow_regs[0x6c];
 | 
						|
      DBG (7, "startx=%d, endx=%d, pixels=%d, coef=%d, r2f=0x%02x\n", sx, ex,
 | 
						|
	   ex - sx, dev->shadow_regs[0x7a], shadow_regs[0x2f]);
 | 
						|
      sy = shadow_regs[0x61] * 256 + shadow_regs[0x60];
 | 
						|
      ey = shadow_regs[0x63] * 256 + shadow_regs[0x62];
 | 
						|
      DBG (7, "starty=%d, endy=%d, lines=%d\n", sy, ey, ey - sy);
 | 
						|
    }
 | 
						|
 | 
						|
  /* we use register 0xb0 to identify details about models   */
 | 
						|
  /* this register isn't overwritten during normal operation */
 | 
						|
  if (shadow_regs[0xb0] == 0x2c && dev->model.sensor_type == X1100_B2_SENSOR)
 | 
						|
    {
 | 
						|
      variant = shadow_regs[0xb0];
 | 
						|
    }
 | 
						|
  /* now the same with register 0x10 */
 | 
						|
  /* which most likely signals USB2.0/USB1.1 */
 | 
						|
  if ((dev->model.sensor_type == X1200_SENSOR) && (shadow_regs[0x10] == 0x97))
 | 
						|
    {
 | 
						|
      variant = shadow_regs[0x10];
 | 
						|
    }
 | 
						|
 | 
						|
  /* if find a case where default model given is inappropriate, reassign it
 | 
						|
   * since we have now the informations to get the real one. Such
 | 
						|
   * We could avoid this if attach() did open and read registers, not init */
 | 
						|
  if (variant != 0)
 | 
						|
    {
 | 
						|
      DBG (3,
 | 
						|
	   "sanei_lexmark_low_open_device: reassign model/sensor for varaint 0x%02x\n",
 | 
						|
	   variant);
 | 
						|
      sanei_lexmark_low_assign_model (dev, dev->sane.name,
 | 
						|
					dev->model.vendor_id,
 | 
						|
					dev->model.product_id, variant);
 | 
						|
      /* since model has changed, run init again */
 | 
						|
      sanei_lexmark_low_init (dev);
 | 
						|
    }
 | 
						|
  DBG (2, "sanei_lexmark_low_open_device: end\n");
 | 
						|
  return result;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
sanei_lexmark_low_close_device (Lexmark_Device * dev)
 | 
						|
{
 | 
						|
  /* put scanner in idle state */
 | 
						|
  lexmark_low_set_idle (dev->devnum);
 | 
						|
 | 
						|
  /* This function calls the Sane USB library to close this usb device */
 | 
						|
#ifndef FAKE_USB
 | 
						|
  sanei_usb_close (dev->devnum);
 | 
						|
#endif
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* This function writes the contents of the given registers to the 
 | 
						|
     scanner. */
 | 
						|
SANE_Status
 | 
						|
low_write_all_regs (SANE_Int devnum, SANE_Byte * regs)
 | 
						|
{
 | 
						|
  int i;
 | 
						|
  SANE_Status status;
 | 
						|
  size_t size;
 | 
						|
  static SANE_Byte command_block1[0xb7];
 | 
						|
  static SANE_Byte command_block2[0x4f];
 | 
						|
  command_block1[0] = 0x88;
 | 
						|
  command_block1[1] = 0x00;
 | 
						|
  command_block1[2] = 0x00;
 | 
						|
  command_block1[3] = 0xb3;
 | 
						|
  for (i = 0; i < 0xb3; i++)
 | 
						|
    {
 | 
						|
      command_block1[i + 4] = regs[i];
 | 
						|
    }
 | 
						|
  command_block2[0] = 0x88;
 | 
						|
  command_block2[1] = 0xb4;
 | 
						|
  command_block2[2] = 0x00;
 | 
						|
  command_block2[3] = 0x4b;
 | 
						|
  for (i = 0; i < 0x4b; i++)
 | 
						|
    {
 | 
						|
      command_block2[i + 4] = regs[i + 0xb4];
 | 
						|
    }
 | 
						|
  size = 0xb7;
 | 
						|
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
  fprintf (stderr, "write_all(0x00,255)=");
 | 
						|
  for (i = 0; i < 255; i++)
 | 
						|
    {
 | 
						|
      fprintf (stderr, "0x%02x ", regs[i]);
 | 
						|
    }
 | 
						|
  fprintf (stderr, "\n");
 | 
						|
#endif
 | 
						|
 | 
						|
  status = low_usb_bulk_write (devnum, command_block1, &size);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    return status;
 | 
						|
  size = 0x4f;
 | 
						|
  status = low_usb_bulk_write (devnum, command_block2, &size);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    return status;
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
SANE_Bool
 | 
						|
low_is_home_line (unsigned char *buffer)
 | 
						|
{
 | 
						|
  /*
 | 
						|
     This function assumes the buffer has a size of 2500 bytes.It is 
 | 
						|
     destructive to the buffer.
 | 
						|
 | 
						|
     Here is what it does:
 | 
						|
 | 
						|
     Go through the buffer finding low and high values, which are computed by 
 | 
						|
     comparing to the average: 
 | 
						|
     average = (lowest value + highest value)/2
 | 
						|
     High bytes are changed to 0xFF (white), lower or equal bytes are changed 
 | 
						|
     to 0x00 (black),so that the buffer only contains white (0xFF) or black 
 | 
						|
     (0x00) values.
 | 
						|
 | 
						|
     Next, we go through the buffer. We use a tolerance of 5 bytes on each end
 | 
						|
     of the buffer and check a region from bytes 5 to 2495. We start assuming
 | 
						|
     we are in a white region and look for the start of a black region. We save
 | 
						|
     this index as the transition from white to black. We also save where we 
 | 
						|
     change from black back to white. We continue checking for transitions 
 | 
						|
     until the end of the check region. If we don't have exactly two 
 | 
						|
     transitions when we reach the end we return SANE_FALSE.
 | 
						|
 | 
						|
     The final check compares the transition indices to the nominal values
 | 
						|
     plus or minus the tolerence. For the first transition (white to black
 | 
						|
     index) the value must lie in the range 1235-30 (1205) to 1235+30 (1265).
 | 
						|
     For the second transition (black to white) the value must lie in the range
 | 
						|
     1258-30 (1228) to 1258+30 (1288). If the indices are out of range we 
 | 
						|
     return SANE_FALSE. Otherwise, we return SANE_TRUE.
 | 
						|
   */
 | 
						|
 | 
						|
 | 
						|
  unsigned char max_byte = 0;
 | 
						|
  unsigned char min_byte = 0xFF;
 | 
						|
  unsigned char average;
 | 
						|
  int i;
 | 
						|
 | 
						|
  region_type region;
 | 
						|
  int transition_counter;
 | 
						|
  int index1 = 0;
 | 
						|
  int index2 = 0;
 | 
						|
  int low_range, high_range;
 | 
						|
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
  static int numero = 0;
 | 
						|
  char titre[80];
 | 
						|
  FILE *trace = NULL;
 | 
						|
  sprintf (titre, "lgn%03d.pnm", numero);
 | 
						|
  trace = fopen (titre, "wb");
 | 
						|
  if (trace)
 | 
						|
    {
 | 
						|
      fprintf (trace, "P5\n2500 1\n255\n");
 | 
						|
      fwrite (buffer, 2500, 1, trace);
 | 
						|
      fclose (trace);
 | 
						|
    }
 | 
						|
  numero++;
 | 
						|
#endif
 | 
						|
 | 
						|
  /* Find the max and the min */
 | 
						|
  for (i = 0; i < 2500; i++)
 | 
						|
    {
 | 
						|
      if (*(buffer + i) > max_byte)
 | 
						|
	max_byte = *(buffer + i);
 | 
						|
      if (*(buffer + i) < min_byte)
 | 
						|
	min_byte = *(buffer + i);
 | 
						|
    }
 | 
						|
 | 
						|
  /* The average */
 | 
						|
  average = ((max_byte + min_byte) / 2);
 | 
						|
 | 
						|
  /* Set bytes as white (0xFF) or black (0x00) */
 | 
						|
  for (i = 0; i < 2500; i++)
 | 
						|
    {
 | 
						|
      if (*(buffer + i) > average)
 | 
						|
	*(buffer + i) = 0xFF;
 | 
						|
      else
 | 
						|
	*(buffer + i) = 0x00;
 | 
						|
    }
 | 
						|
 | 
						|
  region = white;
 | 
						|
  transition_counter = 0;
 | 
						|
 | 
						|
  /* Go through the check region - bytes 5 to 2495 */
 | 
						|
  for (i = 5; i <= 2495; i++)
 | 
						|
    {
 | 
						|
      /* Check for transition to black */
 | 
						|
      if ((region == white) && (*(buffer + i) == 0))
 | 
						|
	{
 | 
						|
	  if (transition_counter < 2)
 | 
						|
	    {
 | 
						|
	      region = black;
 | 
						|
	      index1 = i;
 | 
						|
	      transition_counter++;
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      return SANE_FALSE;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
      /* Check for transition to white */
 | 
						|
      else if ((region == black) && (*(buffer + i) == 0xFF))
 | 
						|
	{
 | 
						|
	  if (transition_counter < 2)
 | 
						|
	    {
 | 
						|
	      region = white;
 | 
						|
	      index2 = i;
 | 
						|
	      transition_counter++;
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      return SANE_FALSE;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  /* Check that the number of transitions is 2 */
 | 
						|
  if (transition_counter != 2)
 | 
						|
    {
 | 
						|
      return SANE_FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
  /* Check that the 1st index is in range */
 | 
						|
  low_range = HomeEdgePoint1 - HomeTolerance;
 | 
						|
  high_range = HomeEdgePoint1 + HomeTolerance;
 | 
						|
 | 
						|
  if ((index1 < low_range) || (index1 > high_range))
 | 
						|
    {
 | 
						|
      return SANE_FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
  /* Check that the 2nd index is in range */
 | 
						|
  low_range = HomeEdgePoint2 - HomeTolerance;
 | 
						|
  high_range = HomeEdgePoint2 + HomeTolerance;
 | 
						|
 | 
						|
  if ((index2 < low_range) || (index2 > high_range))
 | 
						|
    {
 | 
						|
      return SANE_FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
  /* We made it this far, so its a good home line. Return True */
 | 
						|
  return SANE_TRUE;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
sanei_lexmark_low_move_fwd (SANE_Int distance, Lexmark_Device * dev,
 | 
						|
			      SANE_Byte * regs)
 | 
						|
{
 | 
						|
  /*
 | 
						|
     This function moves the scan head forward with the highest vertical 
 | 
						|
     resolution of 1200dpi. The distance moved is given by the distance
 | 
						|
     parameter. 
 | 
						|
 | 
						|
     As an example, given a distance parameter of 600, the scan head will
 | 
						|
     move 600/1200", or 1/2" forward.
 | 
						|
   */
 | 
						|
 | 
						|
  static SANE_Byte pollstopmoving_command_block[] =
 | 
						|
    { 0x80, 0xb3, 0x00, 0x01 };
 | 
						|
 | 
						|
 | 
						|
  size_t cmd_size;
 | 
						|
  SANE_Int devnum;
 | 
						|
  SANE_Bool scan_head_moving;
 | 
						|
  SANE_Byte read_result;
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_move_fwd: \n");
 | 
						|
  devnum = dev->devnum;
 | 
						|
 | 
						|
 | 
						|
  /* registers set-up */
 | 
						|
  regs[0x2c] = 0x00;
 | 
						|
  regs[0x2d] = 0x41;
 | 
						|
  regs[0x65] = 0x80;
 | 
						|
  switch (dev->model.sensor_type)
 | 
						|
    {
 | 
						|
    case X1100_B2_SENSOR:
 | 
						|
      regs[0x8b] = 0x00;
 | 
						|
      regs[0x8c] = 0x00;
 | 
						|
      regs[0x93] = 0x06;
 | 
						|
      break;
 | 
						|
    case X1100_2C_SENSOR:
 | 
						|
      rts88xx_set_scan_frequency (regs, 0);
 | 
						|
      regs[0x93] = 0x06;
 | 
						|
      break;
 | 
						|
    case A920_SENSOR:
 | 
						|
      rts88xx_set_scan_frequency (regs, 0);
 | 
						|
      regs[0x8b] = 0xff;
 | 
						|
      regs[0x8c] = 0x02;
 | 
						|
      regs[0x93] = 0x0e;
 | 
						|
      break;
 | 
						|
    case X1200_SENSOR:
 | 
						|
      dev->shadow_regs[0x2d] = 0x01;
 | 
						|
      rts88xx_set_scan_frequency (regs, 0);
 | 
						|
      break;
 | 
						|
    case X1200_USB2_SENSOR:
 | 
						|
      dev->shadow_regs[0x2d] = 0x4f;
 | 
						|
      rts88xx_set_scan_frequency (regs, 0);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
  /* set grayscale scan + nodata/nochannel?  */
 | 
						|
  regs[0x2f] = 0xa1;
 | 
						|
 | 
						|
  /* set ? */
 | 
						|
  regs[0x34] = 0x50;
 | 
						|
  regs[0x35] = 0x01;
 | 
						|
  regs[0x36] = 0x50;
 | 
						|
  regs[0x37] = 0x01;
 | 
						|
  regs[0x38] = 0x50;
 | 
						|
  /* set motor resolution divisor */
 | 
						|
  regs[0x39] = 0x00;
 | 
						|
  /* set vertical start/end positions */
 | 
						|
  regs[0x60] = LOBYTE (distance - 1);
 | 
						|
  regs[0x61] = HIBYTE (distance - 1);
 | 
						|
  regs[0x62] = LOBYTE (distance);
 | 
						|
  regs[0x63] = HIBYTE (distance);
 | 
						|
  /* set horizontal start position */
 | 
						|
  regs[0x66] = 0x64;
 | 
						|
  regs[0x67] = 0x00;
 | 
						|
  /* set horizontal end position */
 | 
						|
  regs[0x6c] = 0xc8;
 | 
						|
  regs[0x6d] = 0x00;
 | 
						|
  /* set horizontal resolution */
 | 
						|
  regs[0x79] = 0x40;
 | 
						|
  regs[0x7a] = 0x01;
 | 
						|
  /* don't buffer data for this scan */
 | 
						|
  regs[0xb2] = 0x04;
 | 
						|
  /* Motor enable & Coordinate space denominator */
 | 
						|
  regs[0xc3] = 0x81;
 | 
						|
  /* ? */
 | 
						|
  regs[0x80] = 0x00;
 | 
						|
  regs[0x81] = 0x00;
 | 
						|
  regs[0x82] = 0x00;
 | 
						|
  regs[0xc5] = 0x0a;
 | 
						|
  /* Movement direction & step size */
 | 
						|
  regs[0xc6] = 0x09;
 | 
						|
  /* step size range2 */
 | 
						|
  regs[0xc9] = 0x3b;
 | 
						|
  /* ? */
 | 
						|
  regs[0xca] = 0x0a;
 | 
						|
  /* motor curve stuff */
 | 
						|
  regs[0xe0] = 0x00;
 | 
						|
  regs[0xe1] = 0x00;
 | 
						|
  regs[0xe4] = 0x00;
 | 
						|
  regs[0xe5] = 0x00;
 | 
						|
  regs[0xe7] = 0x00;
 | 
						|
  regs[0xe8] = 0x00;
 | 
						|
 | 
						|
  regs[0xe2] = 0x09;
 | 
						|
  regs[0xe3] = 0x1a;
 | 
						|
  regs[0xe6] = 0xdc;
 | 
						|
  regs[0xe9] = 0x1b;
 | 
						|
  regs[0xec] = 0x07;
 | 
						|
  regs[0xef] = 0x03;
 | 
						|
 | 
						|
  /* prepare for register write */
 | 
						|
  low_clr_c6 (devnum);
 | 
						|
  low_stop_mvmt (devnum);
 | 
						|
 | 
						|
/* Move Forward without scanning: */
 | 
						|
  regs[0x32] = 0x00;
 | 
						|
  low_write_all_regs (devnum, regs);
 | 
						|
  regs[0x32] = 0x40;
 | 
						|
  low_write_all_regs (devnum, regs);
 | 
						|
 | 
						|
  /* Stop scanner - clear reg 0xb3: */
 | 
						|
  /* low_stop_mvmt (devnum); */
 | 
						|
 | 
						|
  rts88xx_commit (devnum, regs[0x2c]);
 | 
						|
 | 
						|
  /* Poll for scanner stopped - return value(3:0) = 0: */
 | 
						|
  scan_head_moving = SANE_TRUE;
 | 
						|
  while (scan_head_moving)
 | 
						|
    {
 | 
						|
#ifdef FAKE_USB
 | 
						|
      scan_head_moving = SANE_FALSE;
 | 
						|
#else
 | 
						|
      cmd_size = 0x04;
 | 
						|
      low_usb_bulk_write (devnum, pollstopmoving_command_block, &cmd_size);
 | 
						|
      cmd_size = 0x1;
 | 
						|
      low_usb_bulk_read (devnum, &read_result, &cmd_size);
 | 
						|
      if ((read_result & 0xF) == 0x0)
 | 
						|
	{
 | 
						|
	  scan_head_moving = SANE_FALSE;
 | 
						|
	}
 | 
						|
#endif
 | 
						|
    }
 | 
						|
  DBG (2, "sanei_lexmark_low_move_fwd: end.\n");
 | 
						|
}
 | 
						|
 | 
						|
SANE_Bool
 | 
						|
sanei_lexmark_low_search_home_fwd (Lexmark_Device * dev)
 | 
						|
{
 | 
						|
  /* This function actually searches backwards one line looking for home */
 | 
						|
 | 
						|
  SANE_Int devnum;
 | 
						|
  int i;
 | 
						|
  SANE_Byte poll_result[3];
 | 
						|
  SANE_Byte *buffer;
 | 
						|
  SANE_Byte temp_byte;
 | 
						|
 | 
						|
  static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 };
 | 
						|
 | 
						|
  static SANE_Byte command5_block[] = { 0x91, 0x00, 0x09, 0xc4 };
 | 
						|
 | 
						|
  size_t cmd_size;
 | 
						|
  SANE_Bool got_line;
 | 
						|
  SANE_Bool ret_val;
 | 
						|
 | 
						|
  devnum = dev->devnum;
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_search_home_fwd:\n");
 | 
						|
 | 
						|
  /* set up registers according to the sensor type */
 | 
						|
  switch (dev->model.sensor_type)
 | 
						|
    {
 | 
						|
    case X1100_B2_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x0f;
 | 
						|
      dev->shadow_regs[0x2d] = 0x51;
 | 
						|
      dev->shadow_regs[0x34] = 0x04;
 | 
						|
      dev->shadow_regs[0x35] = 0x04;
 | 
						|
      dev->shadow_regs[0x36] = 0x08;
 | 
						|
      dev->shadow_regs[0x37] = 0x08;
 | 
						|
      dev->shadow_regs[0x38] = 0x0b;
 | 
						|
      dev->shadow_regs[0x93] = 0x06;
 | 
						|
 | 
						|
      break;
 | 
						|
    case X1100_2C_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x0d;
 | 
						|
      dev->shadow_regs[0x2d] = 0x4f;
 | 
						|
      dev->shadow_regs[0x34] = 0x05;
 | 
						|
      dev->shadow_regs[0x35] = 0x05;
 | 
						|
      dev->shadow_regs[0x36] = 0x09;
 | 
						|
      dev->shadow_regs[0x37] = 0x09;
 | 
						|
      dev->shadow_regs[0x38] = 0x0d;
 | 
						|
      dev->shadow_regs[0x40] = 0x80;
 | 
						|
      dev->shadow_regs[0x72] = 0x35;
 | 
						|
      dev->shadow_regs[0x74] = 0x4e;
 | 
						|
 | 
						|
      dev->shadow_regs[0x85] = 0x20;	/* 05 */
 | 
						|
      dev->shadow_regs[0x86] = 0x00;	/* 05 */
 | 
						|
      dev->shadow_regs[0x87] = 0x00;	/* 05 */
 | 
						|
      dev->shadow_regs[0x88] = 0x00;	/* 45 */
 | 
						|
      dev->shadow_regs[0x89] = 0x00;
 | 
						|
      dev->shadow_regs[0x8b] = 0xff;
 | 
						|
 | 
						|
      dev->shadow_regs[0x93] = 0x06;	/* 0e */
 | 
						|
 | 
						|
      dev->shadow_regs[0x75] = 0x00;	/*    */
 | 
						|
      dev->shadow_regs[0x91] = 0x00;	/* 60 */
 | 
						|
      dev->shadow_regs[0x92] = 0x00;	/* 8d */
 | 
						|
      dev->shadow_regs[0xb1] = 0x00;	/*    */
 | 
						|
      dev->shadow_regs[0xc5] = 0x00;	/*    */
 | 
						|
      dev->shadow_regs[0xca] = 0x00;	/*    */
 | 
						|
      dev->shadow_regs[0xc3] = 0x01;	/*    */
 | 
						|
      break;
 | 
						|
    case A920_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x0d;
 | 
						|
      dev->shadow_regs[0x2d] = 0x4f;
 | 
						|
      dev->shadow_regs[0x34] = 0x05;
 | 
						|
      dev->shadow_regs[0x35] = 0x05;
 | 
						|
      dev->shadow_regs[0x36] = 0x09;
 | 
						|
      dev->shadow_regs[0x37] = 0x09;
 | 
						|
      dev->shadow_regs[0x38] = 0x0d;
 | 
						|
      dev->shadow_regs[0x40] = 0x80;
 | 
						|
      dev->shadow_regs[0x72] = 0x35;
 | 
						|
      dev->shadow_regs[0x74] = 0x4e;
 | 
						|
      dev->shadow_regs[0x85] = 0x05;
 | 
						|
      dev->shadow_regs[0x88] = 0x45;
 | 
						|
      dev->shadow_regs[0x89] = 0x00;
 | 
						|
      dev->shadow_regs[0x8b] = 0xff;
 | 
						|
      dev->shadow_regs[0x91] = 0x60;
 | 
						|
      dev->shadow_regs[0x92] = 0x8d;
 | 
						|
      dev->shadow_regs[0x93] = 0x0e;
 | 
						|
      break;
 | 
						|
    case X1200_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x01;
 | 
						|
      dev->shadow_regs[0x2d] = 0x03;
 | 
						|
      dev->shadow_regs[0x34] = 0x04;
 | 
						|
      dev->shadow_regs[0x35] = 0x04;
 | 
						|
      dev->shadow_regs[0x36] = 0x08;
 | 
						|
      dev->shadow_regs[0x37] = 0x08;
 | 
						|
      dev->shadow_regs[0x38] = 0x0b;
 | 
						|
      dev->shadow_regs[0x66] = 0x88;
 | 
						|
      dev->shadow_regs[0x6c] = 0x10;
 | 
						|
      dev->shadow_regs[0x6d] = 0x14;
 | 
						|
      dev->shadow_regs[0x75] = 0x00;
 | 
						|
      dev->shadow_regs[0x93] = 0x06;
 | 
						|
      dev->shadow_regs[0xc5] = 0x00;
 | 
						|
      dev->shadow_regs[0xca] = 0x00;
 | 
						|
      break;
 | 
						|
    case X1200_USB2_SENSOR:
 | 
						|
      dev->shadow_regs[0x0b] = 0x70;
 | 
						|
      dev->shadow_regs[0x0c] = 0x28;
 | 
						|
      dev->shadow_regs[0x0d] = 0xa4;
 | 
						|
 | 
						|
      dev->shadow_regs[0x2c] = 0x0d;
 | 
						|
      dev->shadow_regs[0x2d] = 0x4f;
 | 
						|
      dev->shadow_regs[0x2f] = 0x21;
 | 
						|
      dev->shadow_regs[0x32] = 0x40;
 | 
						|
      dev->shadow_regs[0x34] = 0x05;
 | 
						|
      dev->shadow_regs[0x35] = 0x05;
 | 
						|
      dev->shadow_regs[0x36] = 0x09;
 | 
						|
      dev->shadow_regs[0x37] = 0x09;
 | 
						|
      dev->shadow_regs[0x38] = 0x0d;
 | 
						|
      dev->shadow_regs[0x3a] = 0x20;
 | 
						|
      dev->shadow_regs[0x3b] = 0x37;
 | 
						|
      dev->shadow_regs[0x40] = 0x80;
 | 
						|
      dev->shadow_regs[0x47] = 0x01;
 | 
						|
      dev->shadow_regs[0x48] = 0x1a;
 | 
						|
      dev->shadow_regs[0x49] = 0x5b;
 | 
						|
      dev->shadow_regs[0x4a] = 0x1b;
 | 
						|
      dev->shadow_regs[0x4b] = 0x5b;
 | 
						|
      dev->shadow_regs[0x4c] = 0x05;
 | 
						|
      dev->shadow_regs[0x4d] = 0x3f;
 | 
						|
      dev->shadow_regs[0x75] = 0x00;
 | 
						|
 | 
						|
      dev->shadow_regs[0x85] = 0x03;
 | 
						|
      dev->shadow_regs[0x86] = 0x33;
 | 
						|
      dev->shadow_regs[0x87] = 0x8f;
 | 
						|
      dev->shadow_regs[0x88] = 0x34;
 | 
						|
 | 
						|
      dev->shadow_regs[0x8b] = 0xff;
 | 
						|
      dev->shadow_regs[0x8e] = 0x60;
 | 
						|
      dev->shadow_regs[0x8f] = 0x80;
 | 
						|
 | 
						|
      dev->shadow_regs[0x91] = 0x59;
 | 
						|
      dev->shadow_regs[0x92] = 0x10;
 | 
						|
      dev->shadow_regs[0x93] = 0x06;
 | 
						|
 | 
						|
      dev->shadow_regs[0xa3] = 0x0d;
 | 
						|
      dev->shadow_regs[0xa4] = 0x5e;
 | 
						|
      dev->shadow_regs[0xa5] = 0x23;
 | 
						|
      dev->shadow_regs[0xb1] = 0x07;
 | 
						|
 | 
						|
      dev->shadow_regs[0xc2] = 0x80;
 | 
						|
      dev->shadow_regs[0xc5] = 0x00;
 | 
						|
      dev->shadow_regs[0xca] = 0x00;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  dev->shadow_regs[0x65] = 0x80;
 | 
						|
  dev->shadow_regs[0x8c] = 0x02;
 | 
						|
  dev->shadow_regs[0x8d] = 0x01;
 | 
						|
  dev->shadow_regs[0xb2] = 0x00;
 | 
						|
  dev->shadow_regs[0xed] = 0x00;
 | 
						|
  dev->shadow_regs[0xee] = 0x00;
 | 
						|
 | 
						|
  rts88xx_set_gain (dev->shadow_regs, dev->sensor->default_gain,
 | 
						|
		    dev->sensor->default_gain, dev->sensor->default_gain);
 | 
						|
  rts88xx_set_offset (dev->shadow_regs, 0x80, 0x80, 0x80);
 | 
						|
 | 
						|
  /* set grayscale scan */
 | 
						|
  rts88xx_set_gray_scan (dev->shadow_regs);
 | 
						|
 | 
						|
  /* set motor resolution divisor */
 | 
						|
  dev->shadow_regs[0x39] = 0x07;
 | 
						|
 | 
						|
  /* set vertical start/end positions */
 | 
						|
  dev->shadow_regs[0x60] = 0x01;
 | 
						|
  dev->shadow_regs[0x61] = 0x00;
 | 
						|
  dev->shadow_regs[0x62] = 0x02;
 | 
						|
  dev->shadow_regs[0x63] = 0x00;
 | 
						|
 | 
						|
  /* set # of head moves per CIS read */
 | 
						|
  rts88xx_set_scan_frequency (dev->shadow_regs, 1);
 | 
						|
 | 
						|
  /* set horizontal start position */
 | 
						|
  dev->shadow_regs[0x66] = 0x6a;	/* 0x88 for X1200 */
 | 
						|
  dev->shadow_regs[0x67] = 0x00;
 | 
						|
  /* set horizontal end position */
 | 
						|
  dev->shadow_regs[0x6c] = 0xf2;	/* 0x1410 for X1200 */
 | 
						|
  dev->shadow_regs[0x6d] = 0x13;
 | 
						|
  /* set horizontal resolution */
 | 
						|
  dev->shadow_regs[0x79] = 0x40;
 | 
						|
  dev->shadow_regs[0x7a] = 0x02;
 | 
						|
  /* Movement direction & step size */
 | 
						|
  dev->shadow_regs[0xc6] = 0x01;
 | 
						|
  /* step size range2 */
 | 
						|
  dev->shadow_regs[0xc9] = 0x3b;
 | 
						|
  /* step size range0 */
 | 
						|
  dev->shadow_regs[0xe2] = 0x01;
 | 
						|
  /* ? */
 | 
						|
  dev->shadow_regs[0xe3] = 0x03;
 | 
						|
 | 
						|
  /* Motor disable & Coordinate space denominator */
 | 
						|
  dev->shadow_regs[0xc3] = 0x01;
 | 
						|
 | 
						|
 | 
						|
  /* Stop the scanner */
 | 
						|
  low_stop_mvmt (devnum);
 | 
						|
 | 
						|
  /* write regs out twice */
 | 
						|
  dev->shadow_regs[0x32] = 0x00;
 | 
						|
  low_write_all_regs (devnum, dev->shadow_regs);
 | 
						|
  dev->shadow_regs[0x32] = 0x40;
 | 
						|
  low_write_all_regs (devnum, dev->shadow_regs);
 | 
						|
 | 
						|
  /* Start Scan */
 | 
						|
  rts88xx_commit (devnum, dev->shadow_regs[0x2c]);
 | 
						|
 | 
						|
  /* Poll the available byte count until not 0 */
 | 
						|
  got_line = SANE_FALSE;
 | 
						|
  while (!got_line)
 | 
						|
    {
 | 
						|
      cmd_size = 4;
 | 
						|
      low_usb_bulk_write (devnum, command4_block, &cmd_size);
 | 
						|
      cmd_size = 0x3;
 | 
						|
      low_usb_bulk_read (devnum, poll_result, &cmd_size);
 | 
						|
      if (!
 | 
						|
	  (poll_result[0] == 0 && poll_result[1] == 0 && poll_result[2] == 0))
 | 
						|
	{
 | 
						|
	  /* if result != 00 00 00 we got data */
 | 
						|
	  got_line = SANE_TRUE;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  /* create buffer for scan data */
 | 
						|
  buffer = calloc (2500, sizeof (char));
 | 
						|
 | 
						|
  /* Tell the scanner to send the data */
 | 
						|
  /* Write: 91 00 09 c4 */
 | 
						|
  cmd_size = 4;
 | 
						|
  low_usb_bulk_write (devnum, command5_block, &cmd_size);
 | 
						|
  /* Read it */
 | 
						|
  cmd_size = 0x09c4;
 | 
						|
  low_usb_bulk_read (devnum, buffer, &cmd_size);
 | 
						|
 | 
						|
  /* Reverse order of bytes in words of buffer */
 | 
						|
  for (i = 0; i < 2500; i = i + 2)
 | 
						|
    {
 | 
						|
      temp_byte = *(buffer + i);
 | 
						|
      *(buffer + i) = *(buffer + i + 1);
 | 
						|
      *(buffer + i + 1) = temp_byte;
 | 
						|
    }
 | 
						|
 | 
						|
  /* check for home position */
 | 
						|
  ret_val = low_is_home_line (buffer);
 | 
						|
 | 
						|
  if (ret_val)
 | 
						|
    DBG (2, "sanei_lexmark_low_search_home_fwd: !!!HOME POSITION!!!\n");
 | 
						|
 | 
						|
  /* free the buffer */
 | 
						|
  free (buffer);
 | 
						|
  DBG (2, "sanei_lexmark_low_search_home_fwd: end.\n");
 | 
						|
 | 
						|
  return ret_val;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
SANE_Bool
 | 
						|
sanei_lexmark_low_search_home_bwd (Lexmark_Device * dev)
 | 
						|
{
 | 
						|
/* This function must only be called if the scan head is past the home dot.
 | 
						|
   It could damage the scanner if not.
 | 
						|
 | 
						|
   This function tells the scanner to do a grayscale scan backwards with a 
 | 
						|
   300dpi resolution. It reads 2500 bytes of data between horizontal
 | 
						|
   co-ordinates 0x6a and 0x13f2.
 | 
						|
 | 
						|
   The scan is set to read between vertical co-ordinates from 0x0a to 0x0f46,
 | 
						|
   or 3900 lines. This equates to 13" at 300dpi, so we must stop the scan
 | 
						|
   before it bangs against the end. A line limit is set so that a maximum of
 | 
						|
   0x0F3C (13"*300dpi) lines can be read.
 | 
						|
 | 
						|
   To read the scan data we create a buffer space large enough to hold 10 
 | 
						|
   lines of data. For each read we poll twice, ignoring the first poll. This 
 | 
						|
   is required for timing. We repeat the double poll until there is data
 | 
						|
   available. The number of lines (or number of buffers in our buffer space)
 | 
						|
   is calculated from the size of the data available from the scanner. The
 | 
						|
   number of buffers is calculated as the space required to hold 1.5 times
 | 
						|
   the the size of the data available from the scanner.
 | 
						|
 | 
						|
   After data is read from the scanner each line is checked if it is on the
 | 
						|
   home dot. Lines are continued to be read until we are no longer on the home
 | 
						|
   dot. */
 | 
						|
 | 
						|
 | 
						|
  SANE_Int devnum;
 | 
						|
  SANE_Status status;
 | 
						|
  int i, j;
 | 
						|
  SANE_Byte poll_result[3];
 | 
						|
  SANE_Byte *buffer;
 | 
						|
  SANE_Byte *buffer_start;
 | 
						|
  SANE_Byte temp_byte;
 | 
						|
 | 
						|
  SANE_Int buffer_count = 0;
 | 
						|
  SANE_Int size_requested;
 | 
						|
  SANE_Int size_returned;
 | 
						|
  SANE_Int no_of_buffers;
 | 
						|
  SANE_Int buffer_limit = 0xF3C;
 | 
						|
  SANE_Int high_byte, mid_byte, low_byte;
 | 
						|
  SANE_Int home_line_count;
 | 
						|
  SANE_Bool in_home_region;
 | 
						|
 | 
						|
  static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 };
 | 
						|
 | 
						|
  static SANE_Byte command5_block[] = { 0x91, 0x00, 0xff, 0xc0 };
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
  FILE *img = NULL;
 | 
						|
#endif
 | 
						|
 | 
						|
  size_t cmd_size;
 | 
						|
  SANE_Bool got_line;
 | 
						|
 | 
						|
  devnum = dev->devnum;
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_search_home_bwd:\n");
 | 
						|
 | 
						|
  /* set up registers */
 | 
						|
  switch (dev->model.sensor_type)
 | 
						|
    {
 | 
						|
    case X1100_B2_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x0f;
 | 
						|
      dev->shadow_regs[0x2d] = 0x51;
 | 
						|
      dev->shadow_regs[0x34] = 0x07;
 | 
						|
      dev->shadow_regs[0x35] = 0x07;
 | 
						|
      dev->shadow_regs[0x36] = 0x0f;
 | 
						|
      dev->shadow_regs[0x37] = 0x0f;
 | 
						|
      dev->shadow_regs[0x38] = 0x15;
 | 
						|
      dev->shadow_regs[0x85] = 0x20;
 | 
						|
      dev->shadow_regs[0x93] = 0x06;
 | 
						|
      break;
 | 
						|
    case X1100_2C_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x0d;
 | 
						|
      dev->shadow_regs[0x2d] = 0x4f;
 | 
						|
      dev->shadow_regs[0x34] = 0x09;
 | 
						|
      dev->shadow_regs[0x35] = 0x09;
 | 
						|
      dev->shadow_regs[0x36] = 0x11;
 | 
						|
      dev->shadow_regs[0x37] = 0x11;
 | 
						|
      dev->shadow_regs[0x38] = 0x19;
 | 
						|
      dev->shadow_regs[0x85] = 0x20;
 | 
						|
      dev->shadow_regs[0x93] = 0x06;
 | 
						|
      break;
 | 
						|
    case A920_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x0d;
 | 
						|
      dev->shadow_regs[0x2d] = 0x4f;
 | 
						|
      dev->shadow_regs[0x34] = 0x09;
 | 
						|
      dev->shadow_regs[0x35] = 0x09;
 | 
						|
      dev->shadow_regs[0x36] = 0x11;
 | 
						|
      dev->shadow_regs[0x37] = 0x11;
 | 
						|
      dev->shadow_regs[0x38] = 0x19;
 | 
						|
      dev->shadow_regs[0x85] = 0x05;
 | 
						|
      dev->shadow_regs[0x93] = 0x0e;
 | 
						|
      break;
 | 
						|
    case X1200_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x01;
 | 
						|
      dev->shadow_regs[0x2d] = 0x03;
 | 
						|
      dev->shadow_regs[0x34] = 0x07;
 | 
						|
      dev->shadow_regs[0x35] = 0x07;
 | 
						|
      dev->shadow_regs[0x36] = 0x0f;
 | 
						|
      dev->shadow_regs[0x37] = 0x0f;
 | 
						|
      dev->shadow_regs[0x38] = 0x15;
 | 
						|
      break;
 | 
						|
    case X1200_USB2_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x0d;
 | 
						|
      dev->shadow_regs[0x2d] = 0x4f;
 | 
						|
      dev->shadow_regs[0x34] = 0x09;
 | 
						|
      dev->shadow_regs[0x35] = 0x09;
 | 
						|
      dev->shadow_regs[0x36] = 0x11;
 | 
						|
      dev->shadow_regs[0x37] = 0x11;
 | 
						|
      dev->shadow_regs[0x38] = 0x19;
 | 
						|
      dev->shadow_regs[0x85] = 0x03;
 | 
						|
      dev->shadow_regs[0x93] = 0x06;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  rts88xx_set_gain (dev->shadow_regs, dev->sensor->default_gain,
 | 
						|
		    dev->sensor->default_gain, dev->sensor->default_gain);
 | 
						|
  dev->shadow_regs[0x65] = 0x80;
 | 
						|
  dev->shadow_regs[0x8b] = 0xff;
 | 
						|
  dev->shadow_regs[0x8c] = 0x02;
 | 
						|
  dev->shadow_regs[0xb2] = 0x00;
 | 
						|
 | 
						|
  /* set calibration */
 | 
						|
  rts88xx_set_offset (dev->shadow_regs, 0x80, 0x80, 0x80);
 | 
						|
 | 
						|
  /* set grayscale  scan  */
 | 
						|
  dev->shadow_regs[0x2f] = 0x21;
 | 
						|
  /* set motor resolution divisor */
 | 
						|
  dev->shadow_regs[0x39] = 0x03;
 | 
						|
  /* set vertical start/end positions */
 | 
						|
  dev->shadow_regs[0x60] = 0x0a;
 | 
						|
  dev->shadow_regs[0x61] = 0x00;
 | 
						|
  dev->shadow_regs[0x62] = 0x46;
 | 
						|
  dev->shadow_regs[0x63] = 0x0f;
 | 
						|
  /* set # of head moves per CIS read */
 | 
						|
  rts88xx_set_scan_frequency (dev->shadow_regs, 2);
 | 
						|
  /* set horizontal start position */
 | 
						|
  dev->shadow_regs[0x66] = 0x6a;	/* 0x88 for X1200 */
 | 
						|
  dev->shadow_regs[0x67] = 0x00;
 | 
						|
  /* set horizontal end position */
 | 
						|
  dev->shadow_regs[0x6c] = 0xf2;	/* 0x1410 for X1200, 13f2 for X1200/rev. 97 */
 | 
						|
  dev->shadow_regs[0x6d] = 0x13;
 | 
						|
  /* set horizontal resolution */
 | 
						|
  dev->shadow_regs[0x79] = 0x40;
 | 
						|
  dev->shadow_regs[0x7a] = 0x02;
 | 
						|
  /* Motor enable & Coordinate space denominator */
 | 
						|
  dev->shadow_regs[0xc3] = 0x81;
 | 
						|
  /* ? */
 | 
						|
  dev->shadow_regs[0xc5] = 0x19;
 | 
						|
  /* Movement direction & step size */
 | 
						|
  dev->shadow_regs[0xc6] = 0x01;
 | 
						|
  /* step size range2 */
 | 
						|
  dev->shadow_regs[0xc9] = 0x3a;
 | 
						|
  /* ? */
 | 
						|
  dev->shadow_regs[0xca] = 0x08;
 | 
						|
  /* motor curve stuff */
 | 
						|
  dev->shadow_regs[0xe0] = 0xe3;
 | 
						|
  dev->shadow_regs[0xe1] = 0x18;
 | 
						|
  dev->shadow_regs[0xe2] = 0x03;
 | 
						|
  dev->shadow_regs[0xe3] = 0x06;
 | 
						|
  dev->shadow_regs[0xe4] = 0x2b;
 | 
						|
  dev->shadow_regs[0xe5] = 0x17;
 | 
						|
  dev->shadow_regs[0xe6] = 0xdc;
 | 
						|
  dev->shadow_regs[0xe7] = 0xb3;
 | 
						|
  dev->shadow_regs[0xe8] = 0x07;
 | 
						|
  dev->shadow_regs[0xe9] = 0x1b;
 | 
						|
  dev->shadow_regs[0xec] = 0x07;
 | 
						|
  dev->shadow_regs[0xef] = 0x03;
 | 
						|
 | 
						|
  /* Stop the scanner */
 | 
						|
  low_stop_mvmt (devnum);
 | 
						|
 | 
						|
  /* write regs out twice */
 | 
						|
  dev->shadow_regs[0x32] = 0x00;
 | 
						|
  low_write_all_regs (devnum, dev->shadow_regs);
 | 
						|
  dev->shadow_regs[0x32] = 0x40;
 | 
						|
  low_write_all_regs (devnum, dev->shadow_regs);
 | 
						|
 | 
						|
  /* Start Scan */
 | 
						|
  status = rts88xx_commit (devnum, dev->shadow_regs[0x2c]);
 | 
						|
 | 
						|
  /* create buffer to hold up to 10 lines of  scan data */
 | 
						|
  buffer = calloc (10 * 2500, sizeof (char));
 | 
						|
 | 
						|
  home_line_count = 0;
 | 
						|
  in_home_region = SANE_FALSE;
 | 
						|
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
  img = fopen ("find_bwd.pnm", "wb");
 | 
						|
  fprintf (img, "P5\n2500 100\n255\n");
 | 
						|
#endif
 | 
						|
  while (buffer_count < buffer_limit)
 | 
						|
    {
 | 
						|
      size_returned = 0;
 | 
						|
      got_line = SANE_FALSE;
 | 
						|
      while (!got_line)
 | 
						|
	{
 | 
						|
	  /* always poll twice (needed for timing) - disregard 1st poll */
 | 
						|
	  cmd_size = 4;
 | 
						|
	  status = low_usb_bulk_write (devnum, command4_block, &cmd_size);
 | 
						|
	  if (status != SANE_STATUS_GOOD)
 | 
						|
	    return SANE_FALSE;
 | 
						|
	  cmd_size = 0x3;
 | 
						|
	  status = low_usb_bulk_read (devnum, poll_result, &cmd_size);
 | 
						|
	  if (status != SANE_STATUS_GOOD)
 | 
						|
	    return SANE_FALSE;
 | 
						|
	  cmd_size = 4;
 | 
						|
	  status = low_usb_bulk_write (devnum, command4_block, &cmd_size);
 | 
						|
	  if (status != SANE_STATUS_GOOD)
 | 
						|
	    return SANE_FALSE;
 | 
						|
	  cmd_size = 0x3;
 | 
						|
	  status = low_usb_bulk_read (devnum, poll_result, &cmd_size);
 | 
						|
	  if (status != SANE_STATUS_GOOD)
 | 
						|
	    return SANE_FALSE;
 | 
						|
	  if (!
 | 
						|
	      (poll_result[0] == 0 && poll_result[1] == 0
 | 
						|
	       && poll_result[2] == 0))
 | 
						|
	    {
 | 
						|
	      /* if result != 00 00 00 we got data */
 | 
						|
	      got_line = SANE_TRUE;
 | 
						|
	      high_byte = poll_result[2] << 16;
 | 
						|
	      mid_byte = poll_result[1] << 8;
 | 
						|
	      low_byte = poll_result[0];
 | 
						|
	      size_returned = high_byte + mid_byte + low_byte;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
      size_requested = size_returned;
 | 
						|
      size_requested = 2500;
 | 
						|
      no_of_buffers = size_returned * 3;
 | 
						|
      no_of_buffers = no_of_buffers / 2500;
 | 
						|
      no_of_buffers = no_of_buffers >> 1;
 | 
						|
      /* force 1 buffer at a time to improve accuray, which slow downs search */
 | 
						|
      no_of_buffers = 1;
 | 
						|
 | 
						|
      if (no_of_buffers < 1)
 | 
						|
	no_of_buffers = 1;
 | 
						|
      else if (no_of_buffers > 10)
 | 
						|
	no_of_buffers = 10;
 | 
						|
      buffer_count = buffer_count + no_of_buffers;
 | 
						|
      size_requested = no_of_buffers * 2500;
 | 
						|
 | 
						|
      /* Tell the scanner to send the data */
 | 
						|
      /* Write: 91 <size_requested> */
 | 
						|
      command5_block[1] = (SANE_Byte) (size_requested >> 16);
 | 
						|
      command5_block[2] = (SANE_Byte) (size_requested >> 8);
 | 
						|
      command5_block[3] = (SANE_Byte) (size_requested & 0xFF);
 | 
						|
 | 
						|
      cmd_size = 4;
 | 
						|
      status = low_usb_bulk_write (devnum, command5_block, &cmd_size);
 | 
						|
      if (status != SANE_STATUS_GOOD)
 | 
						|
	return SANE_FALSE;
 | 
						|
      /* Read it */
 | 
						|
      cmd_size = size_requested;
 | 
						|
      status = low_usb_bulk_read (devnum, buffer, &cmd_size);
 | 
						|
      if (status != SANE_STATUS_GOOD)
 | 
						|
	return SANE_FALSE;
 | 
						|
      for (i = 0; i < no_of_buffers; i++)
 | 
						|
	{
 | 
						|
	  buffer_start = buffer + (i * 2500);
 | 
						|
	  /* Reverse order of bytes in words of buffer */
 | 
						|
	  for (j = 0; j < 2500; j = j + 2)
 | 
						|
	    {
 | 
						|
	      temp_byte = *(buffer_start + j);
 | 
						|
	      *(buffer_start + j) = *(buffer_start + j + 1);
 | 
						|
	      *(buffer_start + j + 1) = temp_byte;
 | 
						|
	    }
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
	  fwrite (buffer + (i * 2500), 2500, 1, img);
 | 
						|
#endif
 | 
						|
	  if (low_is_home_line (buffer_start))
 | 
						|
	    {
 | 
						|
	      home_line_count++;
 | 
						|
	      if (home_line_count > 7)
 | 
						|
		in_home_region = SANE_TRUE;
 | 
						|
	    }
 | 
						|
	  if (in_home_region)
 | 
						|
	    {
 | 
						|
	      /* slow down scanning : on purpose backtracking */
 | 
						|
	      if (home_line_count)
 | 
						|
		sleep (1);
 | 
						|
	      free (buffer);
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
	      fflush (img);
 | 
						|
	      i = ftell (img) / 2500;
 | 
						|
	      rewind (img);
 | 
						|
	      DBG (2, "sanei_lexmark_low_search_home_bwd: offset=%d\n", i);
 | 
						|
	      fprintf (img, "P5\n2500 %03d\n", i);
 | 
						|
	      fclose (img);
 | 
						|
#endif
 | 
						|
	      low_stop_mvmt (devnum);
 | 
						|
	      DBG (2,
 | 
						|
		   "sanei_lexmark_low_search_home_bwd: in home region, end.\n");
 | 
						|
	      return SANE_TRUE;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }				/*   end while (buffer_count > buffer_limit); */
 | 
						|
  free (buffer);
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
  fflush (img);
 | 
						|
  i = ftell (img) / 2500;
 | 
						|
  rewind (img);
 | 
						|
  fprintf (img, "P5\n2500 %03d\n", i);
 | 
						|
  fclose (img);
 | 
						|
#endif
 | 
						|
  low_stop_mvmt (devnum);
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_search_home_bwd: end.\n");
 | 
						|
 | 
						|
  return SANE_FALSE;
 | 
						|
}
 | 
						|
 | 
						|
SANE_Status
 | 
						|
low_get_start_loc (SANE_Int resolution, SANE_Int * vert_start,
 | 
						|
		     SANE_Int * hor_start, SANE_Int offset,
 | 
						|
		     Lexmark_Device * dev)
 | 
						|
{
 | 
						|
  SANE_Int start_600;
 | 
						|
 | 
						|
  /* Calculate vertical start distance at 600dpi */
 | 
						|
  start_600 = 195 - offset;
 | 
						|
 | 
						|
  switch (resolution)
 | 
						|
    {
 | 
						|
    case 75:
 | 
						|
      *vert_start = start_600 / 8;
 | 
						|
      *hor_start = 0x68;
 | 
						|
      break;
 | 
						|
    case 150:
 | 
						|
      *vert_start = start_600 / 4;
 | 
						|
      *hor_start = 0x68;
 | 
						|
      break;
 | 
						|
    case 300:
 | 
						|
      *vert_start = start_600 / 2;
 | 
						|
      *hor_start = 0x6a;
 | 
						|
      break;
 | 
						|
    case 600:
 | 
						|
      *vert_start = start_600;
 | 
						|
      *hor_start = 0x6b;
 | 
						|
      break;
 | 
						|
    case 1200:
 | 
						|
      *vert_start = start_600 * 2;
 | 
						|
      *hor_start = 0x6b;
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      /* If we're here we have an invalid resolution */
 | 
						|
      return SANE_STATUS_INVAL;
 | 
						|
    }
 | 
						|
 | 
						|
  /* maybe left margin could be autodetected */
 | 
						|
  if (dev->model.sensor_type != X1100_B2_SENSOR)
 | 
						|
    *hor_start = 0x68;
 | 
						|
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
low_set_scan_area (SANE_Int res,
 | 
						|
		     SANE_Int tlx,
 | 
						|
		     SANE_Int tly,
 | 
						|
		     SANE_Int brx,
 | 
						|
		     SANE_Int bry,
 | 
						|
		     SANE_Int offset,
 | 
						|
		     SANE_Bool half_step,
 | 
						|
		     SANE_Byte * regs, Lexmark_Device * dev)
 | 
						|
{
 | 
						|
 | 
						|
  SANE_Status status;
 | 
						|
  SANE_Int vert_start;
 | 
						|
  SANE_Int hor_start;
 | 
						|
  SANE_Int vert_end;
 | 
						|
  SANE_Int hor_end;
 | 
						|
 | 
						|
  status = low_get_start_loc (res, &vert_start, &hor_start, offset, dev);
 | 
						|
 | 
						|
  /* convert pixel height to vertical location coordinates */
 | 
						|
  vert_end = vert_start + (bry * res) / 600;
 | 
						|
  vert_start += (tly * res) / 600;
 | 
						|
 | 
						|
  /* scan area size : for A920, 600 color scans are done at 1200 y dpi */
 | 
						|
  /* this follow what was found in usb logs                            */
 | 
						|
  if (half_step)
 | 
						|
    {
 | 
						|
      vert_end = vert_end * 2;
 | 
						|
      vert_start = vert_start * 2;
 | 
						|
    }
 | 
						|
 | 
						|
  /* set vertical start position registers */
 | 
						|
  regs[0x60] = LOBYTE (vert_start);
 | 
						|
  regs[0x61] = HIBYTE (vert_start);
 | 
						|
  /* set vertical end position registers */
 | 
						|
  regs[0x62] = LOBYTE (vert_end);
 | 
						|
  regs[0x63] = HIBYTE (vert_end);
 | 
						|
 | 
						|
  /* convert pixel width to horizontal location coordinates */
 | 
						|
  hor_end = hor_start + brx;
 | 
						|
 | 
						|
  /* set horizontal start position registers */
 | 
						|
  hor_start += tlx;
 | 
						|
  regs[0x66] = LOBYTE (hor_start);
 | 
						|
  regs[0x67] = HIBYTE (hor_start);
 | 
						|
  /* set horizontal end position registers */
 | 
						|
  regs[0x6c] = LOBYTE (hor_end);
 | 
						|
  regs[0x6d] = HIBYTE (hor_end);
 | 
						|
 | 
						|
  /* Debug */
 | 
						|
  DBG (2, "low_set_scan_area: vert_start: %d (tly=%d)\n", vert_start, tly);
 | 
						|
  DBG (2, "low_set_scan_area: vert_end: %d\n", vert_end);
 | 
						|
  DBG (2, "low_set_scan_area: hor_start: %d\n", hor_start);
 | 
						|
  DBG (2, "low_set_scan_area: hor_end: %d\n", hor_end);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
SANE_Int
 | 
						|
sanei_lexmark_low_find_start_line (Lexmark_Device * dev)
 | 
						|
{
 | 
						|
  /*
 | 
						|
     This function scans forward 59 lines, reading 88 bytes per line from the
 | 
						|
     middle of the horizontal line: pixel 0xa84 to pixel 0x9d4. It scans with
 | 
						|
     the following parameters:
 | 
						|
     dir=fwd 
 | 
						|
     mode=grayscale
 | 
						|
     h.res=300 dpi
 | 
						|
     v.res=600 dpi   
 | 
						|
     hor. pixels = (0xa84 - 0x9d4)/2 = 0x58 = 88
 | 
						|
     vert. pixels = 0x3e - 0x03 = 0x3b = 59
 | 
						|
     data = 88x59=5192=0x1448
 | 
						|
 | 
						|
     It assumes we are in the start dot, or just before it. We are reading
 | 
						|
     enough lines at 600dpi to read past the dot. We return the number of
 | 
						|
     entirely white lines read consecutively, so we know how far past the
 | 
						|
     dot we are.
 | 
						|
 | 
						|
     To find the number of consecutive white lines we do the following:
 | 
						|
 | 
						|
     Byte swap the order of the bytes in the buffer.
 | 
						|
 | 
						|
     Go through the buffer finding low and high values, which are computed by 
 | 
						|
     comparing to the weighted average: 
 | 
						|
     weighted_average = (lowest value + (highest value - lowest value)/4)
 | 
						|
     Low bytes are changed to 0xFF (white), higher of equal bytes are changed 
 | 
						|
     to 0x00 (black),so that the buffer only contains white (0xFF) or black 
 | 
						|
     (0x00) values.
 | 
						|
 | 
						|
     Next, we go through the buffer a line (88 bytes) at a time for 59 lines
 | 
						|
     to read the entire buffer. For each byte in a line we check if the
 | 
						|
     byte is black. If it is we increment the black byte counter.
 | 
						|
 | 
						|
     After each line we check the black byte counter. If it is greater than 0 
 | 
						|
     we increment the black line count and set the white line count to 0. If
 | 
						|
     there were no black bytes in the line we set the black line count to 0
 | 
						|
     and increment the white line count.
 | 
						|
 | 
						|
     When all lines have been processed we return the white line count.
 | 
						|
   */
 | 
						|
 | 
						|
 | 
						|
  int blackLineCount = 0;
 | 
						|
  int whiteLineCount = 0;
 | 
						|
  int blackByteCounter = 0;
 | 
						|
  unsigned char max_byte = 0;
 | 
						|
  unsigned char min_byte = 0xFF;
 | 
						|
  unsigned char weighted_average;
 | 
						|
  int i, j;
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
  FILE *fdbg = NULL;
 | 
						|
#endif
 | 
						|
 | 
						|
  SANE_Byte poll_result[3];
 | 
						|
  SANE_Byte *buffer;
 | 
						|
  SANE_Byte temp_byte;
 | 
						|
 | 
						|
  static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 };
 | 
						|
 | 
						|
  static SANE_Byte command5_block[] = { 0x91, 0x00, 0x14, 0x48 };
 | 
						|
 | 
						|
  size_t cmd_size;
 | 
						|
  SANE_Bool got_line;
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_find_start_line:\n");
 | 
						|
 | 
						|
  /* set up registers */
 | 
						|
  switch (dev->model.sensor_type)
 | 
						|
    {
 | 
						|
    case X1100_B2_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x0f;
 | 
						|
      dev->shadow_regs[0x2d] = 0x51;
 | 
						|
      dev->shadow_regs[0x34] = 0x0d;
 | 
						|
      dev->shadow_regs[0x35] = 0x0d;
 | 
						|
      dev->shadow_regs[0x36] = 0x1d;
 | 
						|
      dev->shadow_regs[0x37] = 0x1d;
 | 
						|
      dev->shadow_regs[0x38] = 0x29;
 | 
						|
      dev->shadow_regs[0x65] = 0x80;
 | 
						|
      dev->shadow_regs[0x85] = 0x00;
 | 
						|
      dev->shadow_regs[0x93] = 0x06;
 | 
						|
      rts88xx_set_gain (dev->shadow_regs, 6, 6, 6);
 | 
						|
      break;
 | 
						|
    case X1100_2C_SENSOR:
 | 
						|
      rts88xx_set_gain (dev->shadow_regs, 10, 10, 10);
 | 
						|
      dev->shadow_regs[0x28] = 0xf5;
 | 
						|
      dev->shadow_regs[0x29] = 0xf7;
 | 
						|
      dev->shadow_regs[0x2a] = 0xf5;
 | 
						|
      dev->shadow_regs[0x2b] = 0x17;
 | 
						|
 | 
						|
      dev->shadow_regs[0x2c] = 0x0d;
 | 
						|
      dev->shadow_regs[0x2d] = 0x4f;
 | 
						|
      dev->shadow_regs[0x31] = 0x01;
 | 
						|
      dev->shadow_regs[0x34] = 0x11;
 | 
						|
      dev->shadow_regs[0x35] = 0x11;
 | 
						|
      dev->shadow_regs[0x36] = 0x21;
 | 
						|
      dev->shadow_regs[0x37] = 0x21;
 | 
						|
      dev->shadow_regs[0x38] = 0x31;
 | 
						|
      dev->shadow_regs[0x72] = 0x35;
 | 
						|
      dev->shadow_regs[0x74] = 0x4e;
 | 
						|
      dev->shadow_regs[0x85] = 0x02;
 | 
						|
      dev->shadow_regs[0x86] = 0x33;
 | 
						|
      dev->shadow_regs[0x87] = 0x0f;
 | 
						|
      dev->shadow_regs[0x88] = 0x24;
 | 
						|
      dev->shadow_regs[0x91] = 0x19;
 | 
						|
      dev->shadow_regs[0x92] = 0x20;
 | 
						|
      dev->shadow_regs[0xea] = 0x00;
 | 
						|
      dev->shadow_regs[0xeb] = 0x00;
 | 
						|
      dev->shadow_regs[0xf3] = 0xf8;
 | 
						|
      dev->shadow_regs[0xf4] = 0x7f;
 | 
						|
      break;
 | 
						|
    case A920_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x0d;
 | 
						|
      dev->shadow_regs[0x2d] = 0x4f;
 | 
						|
      dev->shadow_regs[0x34] = 0x11;
 | 
						|
      dev->shadow_regs[0x35] = 0x11;
 | 
						|
      dev->shadow_regs[0x36] = 0x21;
 | 
						|
      dev->shadow_regs[0x37] = 0x21;
 | 
						|
      dev->shadow_regs[0x38] = 0x31;
 | 
						|
      dev->shadow_regs[0x85] = 0x05;
 | 
						|
      dev->shadow_regs[0x88] = 0x44;
 | 
						|
      dev->shadow_regs[0x92] = 0x85;
 | 
						|
      dev->shadow_regs[0x93] = 0x0e;
 | 
						|
      rts88xx_set_gain (dev->shadow_regs, 6, 6, 6);
 | 
						|
      break;
 | 
						|
    case X1200_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x01;
 | 
						|
      dev->shadow_regs[0x2d] = 0x03;
 | 
						|
      dev->shadow_regs[0x34] = 0x0d;
 | 
						|
      dev->shadow_regs[0x35] = 0x0d;
 | 
						|
      dev->shadow_regs[0x36] = 0x1d;
 | 
						|
      dev->shadow_regs[0x37] = 0x1d;
 | 
						|
      dev->shadow_regs[0x38] = 0x29;
 | 
						|
      dev->shadow_regs[0xea] = 0x00;
 | 
						|
      dev->shadow_regs[0xeb] = 0x00;
 | 
						|
      dev->shadow_regs[0x40] = 0x80;
 | 
						|
      dev->shadow_regs[0x50] = 0x00;
 | 
						|
      dev->shadow_regs[0x81] = 0x00;
 | 
						|
      dev->shadow_regs[0x82] = 0x00;
 | 
						|
      dev->shadow_regs[0x85] = 0x00;
 | 
						|
      dev->shadow_regs[0x86] = 0x00;
 | 
						|
      dev->shadow_regs[0x87] = 0xff;
 | 
						|
      dev->shadow_regs[0x88] = 0x02;
 | 
						|
      dev->shadow_regs[0x92] = 0x00;
 | 
						|
      rts88xx_set_gain (dev->shadow_regs, 10, 10, 10);
 | 
						|
      break;
 | 
						|
    case X1200_USB2_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x01;
 | 
						|
      dev->shadow_regs[0x2d] = 0x03;
 | 
						|
      dev->shadow_regs[0x34] = 0x0d;
 | 
						|
      dev->shadow_regs[0x35] = 0x0d;
 | 
						|
      dev->shadow_regs[0x36] = 0x1d;
 | 
						|
      dev->shadow_regs[0x37] = 0x1d;
 | 
						|
      dev->shadow_regs[0x38] = 0x29;
 | 
						|
      dev->shadow_regs[0xea] = 0x00;
 | 
						|
      dev->shadow_regs[0xeb] = 0x00;
 | 
						|
      rts88xx_set_gain (dev->shadow_regs, 10, 10, 10);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
  /* set offset to a safe value */
 | 
						|
  rts88xx_set_offset (dev->shadow_regs, 0x80, 0x80, 0x80);
 | 
						|
  /* set grayscale  scan  */
 | 
						|
  dev->shadow_regs[0x2f] = 0x21;
 | 
						|
  /* set motor resolution divisor */
 | 
						|
  dev->shadow_regs[0x39] = 0x01;
 | 
						|
  /* set vertical start/end positions */
 | 
						|
  dev->shadow_regs[0x60] = 0x03;
 | 
						|
  dev->shadow_regs[0x61] = 0x00;
 | 
						|
  dev->shadow_regs[0x62] = 0x3e;
 | 
						|
  dev->shadow_regs[0x63] = 0x00;
 | 
						|
  /* set # of head moves per CIS read */
 | 
						|
  rts88xx_set_scan_frequency (dev->shadow_regs, 1);
 | 
						|
  /* set horizontal start position */
 | 
						|
  dev->shadow_regs[0x66] = 0xd4;	/* 0xf2 for X1200 */
 | 
						|
  dev->shadow_regs[0x67] = 0x09;
 | 
						|
  /* set horizontal end position */
 | 
						|
  dev->shadow_regs[0x6c] = 0x84;	/* 0xa2 for X1200 */
 | 
						|
  dev->shadow_regs[0x6d] = 0x0a;
 | 
						|
  /* set horizontal resolution */
 | 
						|
  dev->shadow_regs[0x79] = 0x40;
 | 
						|
  dev->shadow_regs[0x7a] = 0x02;
 | 
						|
  /* set for ? */
 | 
						|
  /* Motor enable & Coordinate space denominator */
 | 
						|
  dev->shadow_regs[0xc3] = 0x81;
 | 
						|
  /* set for ? */
 | 
						|
  dev->shadow_regs[0xc5] = 0x22;
 | 
						|
  /* Movement direction & step size */
 | 
						|
  dev->shadow_regs[0xc6] = 0x09;
 | 
						|
  /* step size range2 */
 | 
						|
  dev->shadow_regs[0xc9] = 0x3b;
 | 
						|
  /* set for ? */
 | 
						|
  dev->shadow_regs[0xca] = 0x1f;
 | 
						|
  dev->shadow_regs[0xe0] = 0xf7;
 | 
						|
  dev->shadow_regs[0xe1] = 0x16;
 | 
						|
  /* step size range0 */
 | 
						|
  dev->shadow_regs[0xe2] = 0x87;
 | 
						|
  /* ? */
 | 
						|
  dev->shadow_regs[0xe3] = 0x13;
 | 
						|
  dev->shadow_regs[0xe4] = 0x1b;
 | 
						|
  dev->shadow_regs[0xe5] = 0x16;
 | 
						|
  dev->shadow_regs[0xe6] = 0xdc;
 | 
						|
  dev->shadow_regs[0xe7] = 0x00;
 | 
						|
  dev->shadow_regs[0xe8] = 0x00;
 | 
						|
  dev->shadow_regs[0xe9] = 0x1b;
 | 
						|
  dev->shadow_regs[0xec] = 0x07;
 | 
						|
  dev->shadow_regs[0xef] = 0x03;
 | 
						|
 | 
						|
  /* Stop the scanner */
 | 
						|
  low_stop_mvmt (dev->devnum);
 | 
						|
 | 
						|
  /* write regs out twice */
 | 
						|
  dev->shadow_regs[0x32] = 0x00;
 | 
						|
  low_write_all_regs (dev->devnum, dev->shadow_regs);
 | 
						|
  dev->shadow_regs[0x32] = 0x40;
 | 
						|
  low_write_all_regs (dev->devnum, dev->shadow_regs);
 | 
						|
 | 
						|
  /* Start Scan */
 | 
						|
  rts88xx_commit (dev->devnum, dev->shadow_regs[0x2c]);
 | 
						|
 | 
						|
  /* Poll the available byte count until not 0 */
 | 
						|
  got_line = SANE_FALSE;
 | 
						|
  while (!got_line)
 | 
						|
    {
 | 
						|
      cmd_size = 4;
 | 
						|
      low_usb_bulk_write (dev->devnum, command4_block, &cmd_size);
 | 
						|
      cmd_size = 0x3;
 | 
						|
      low_usb_bulk_read (dev->devnum, poll_result, &cmd_size);
 | 
						|
      if (!
 | 
						|
	  (poll_result[0] == 0 && poll_result[1] == 0 && poll_result[2] == 0))
 | 
						|
	{
 | 
						|
	  /* if result != 00 00 00 we got data */
 | 
						|
	  got_line = SANE_TRUE;
 | 
						|
	}
 | 
						|
#ifdef FAKE_USB
 | 
						|
      got_line = SANE_TRUE;
 | 
						|
#endif
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
  /* create buffer for scan data */
 | 
						|
  buffer = calloc (5192, sizeof (char));
 | 
						|
 | 
						|
  /* Tell the scanner to send the data */
 | 
						|
  /* Write: 91 00 14 48 */
 | 
						|
  cmd_size = 4;
 | 
						|
  low_usb_bulk_write (dev->devnum, command5_block, &cmd_size);
 | 
						|
  /* Read it */
 | 
						|
  cmd_size = 0x1448;
 | 
						|
  low_usb_bulk_read (dev->devnum, buffer, &cmd_size);
 | 
						|
 | 
						|
  /* Stop the scanner */
 | 
						|
  low_stop_mvmt (dev->devnum);
 | 
						|
 | 
						|
 | 
						|
  /* Reverse order of bytes in words of buffer */
 | 
						|
  for (i = 0; i < 5192; i = i + 2)
 | 
						|
    {
 | 
						|
      temp_byte = *(buffer + i);
 | 
						|
      *(buffer + i) = *(buffer + i + 1);
 | 
						|
      *(buffer + i + 1) = temp_byte;
 | 
						|
    }
 | 
						|
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
  fdbg = fopen ("find_start.pnm", "wb");
 | 
						|
  if (fdbg != NULL)
 | 
						|
    {
 | 
						|
      fprintf (fdbg, "P5\n%d %d\n255\n", 88, 59);
 | 
						|
      fwrite (buffer, 5192, 1, fdbg);
 | 
						|
      fclose (fdbg);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
  /* Find the max and the min */
 | 
						|
  for (i = 0; i < 5192; i++)
 | 
						|
    {
 | 
						|
      if (*(buffer + i) > max_byte)
 | 
						|
	max_byte = *(buffer + i);
 | 
						|
      if (*(buffer + i) < min_byte)
 | 
						|
	min_byte = *(buffer + i);
 | 
						|
    }
 | 
						|
 | 
						|
  weighted_average = min_byte + ((max_byte - min_byte) / 4);
 | 
						|
 | 
						|
  /* Set bytes as black (0x00) or white (0xFF) */
 | 
						|
  for (i = 0; i < 5192; i++)
 | 
						|
    {
 | 
						|
      if (*(buffer + i) > weighted_average)
 | 
						|
	*(buffer + i) = 0xFF;
 | 
						|
      else
 | 
						|
	*(buffer + i) = 0x00;
 | 
						|
    }
 | 
						|
 | 
						|
  /* Go through 59 lines */
 | 
						|
  for (j = 0; j < 59; j++)
 | 
						|
    {
 | 
						|
      blackByteCounter = 0;
 | 
						|
      /* Go through 88 bytes per line */
 | 
						|
      for (i = 0; i < 88; i++)
 | 
						|
	{
 | 
						|
	  /* Is byte black? */
 | 
						|
	  if (*(buffer + (j * 88) + i) == 0)
 | 
						|
	    {
 | 
						|
	      blackByteCounter++;
 | 
						|
	    }
 | 
						|
	}			/* end for line */
 | 
						|
      if (blackByteCounter > 0)
 | 
						|
	{
 | 
						|
	  /* This was a black line */
 | 
						|
	  blackLineCount++;
 | 
						|
	  whiteLineCount = 0;
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  /* This is a white line */
 | 
						|
	  whiteLineCount++;
 | 
						|
	  blackLineCount = 0;
 | 
						|
	}
 | 
						|
    }				/* end for buffer */
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_find_start_line: end.\n");
 | 
						|
  return whiteLineCount;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
SANE_Status
 | 
						|
sanei_lexmark_low_set_scan_regs (Lexmark_Device * dev, SANE_Int offset,
 | 
						|
				   SANE_Bool calibrated)
 | 
						|
{
 | 
						|
  SANE_Int yres;
 | 
						|
  SANE_Bool isColourScan;
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_set_scan_regs:\n");
 | 
						|
  /* resolution */
 | 
						|
  yres = dev->val[OPT_RESOLUTION].w;
 | 
						|
 | 
						|
  DBG (7, "sanei_lexmark_low_set_scan_regs: yres=%d DPI\n", yres);
 | 
						|
 | 
						|
  /* colour mode */
 | 
						|
  if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0)
 | 
						|
    isColourScan = SANE_TRUE;
 | 
						|
  else
 | 
						|
    isColourScan = SANE_FALSE;
 | 
						|
 | 
						|
  /* set up registers */
 | 
						|
  switch (dev->model.sensor_type)
 | 
						|
    {
 | 
						|
    case X1100_B2_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x0f;
 | 
						|
      dev->shadow_regs[0x2d] = 0x51;
 | 
						|
      break;
 | 
						|
    case X1100_2C_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x0d;
 | 
						|
      dev->shadow_regs[0x2d] = 0x4f;
 | 
						|
      break;
 | 
						|
    case A920_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x0d;
 | 
						|
      dev->shadow_regs[0x2d] = 0x4f;
 | 
						|
      break;
 | 
						|
    case X1200_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x01;
 | 
						|
      dev->shadow_regs[0x2d] = 0x03;
 | 
						|
      break;
 | 
						|
    case X1200_USB2_SENSOR:
 | 
						|
      dev->shadow_regs[0x2c] = 0x01;
 | 
						|
      dev->shadow_regs[0x2d] = 0x03;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
  low_set_scan_area (yres,
 | 
						|
		       dev->val[OPT_TL_X].w,
 | 
						|
		       dev->val[OPT_TL_Y].w,
 | 
						|
		       dev->val[OPT_BR_X].w,
 | 
						|
		       dev->val[OPT_BR_Y].w,
 | 
						|
		       offset,
 | 
						|
		       dev->model.motor_type == A920_MOTOR && isColourScan
 | 
						|
		       && (yres == 600), dev->shadow_regs, dev);
 | 
						|
 | 
						|
  /* may be we could use a sensor descriptor that would held the max horiz dpi */
 | 
						|
  if (dev->val[OPT_RESOLUTION].w < 600)
 | 
						|
    dev->shadow_regs[0x7a] = 600 / dev->val[OPT_RESOLUTION].w;
 | 
						|
  else
 | 
						|
    dev->shadow_regs[0x7a] = 1;
 | 
						|
 | 
						|
  /* 75dpi x 75dpi */
 | 
						|
  if (yres == 75)
 | 
						|
    {
 | 
						|
      DBG (5, "sanei_lexmark_low_set_scan_regs(): 75 DPI resolution\n");
 | 
						|
 | 
						|
      if (isColourScan)
 | 
						|
	{
 | 
						|
	  /* set colour scan */
 | 
						|
	  dev->shadow_regs[0x2f] = 0x11;
 | 
						|
 | 
						|
	  switch (dev->model.sensor_type)
 | 
						|
	    {
 | 
						|
	    case X1100_B2_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x05;
 | 
						|
	      dev->shadow_regs[0x36] = 0x05;
 | 
						|
	      dev->shadow_regs[0x38] = 0x05;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x0c;
 | 
						|
	      dev->shadow_regs[0x81] = 0x0c;
 | 
						|
	      dev->shadow_regs[0x82] = 0x09;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x00;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0x00;
 | 
						|
	      dev->shadow_regs[0x88] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x8c;
 | 
						|
	      dev->shadow_regs[0x92] = 0x40;
 | 
						|
	      dev->shadow_regs[0x93] = 0x06;
 | 
						|
	      break;
 | 
						|
 | 
						|
	    case X1100_2C_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x03;
 | 
						|
	      dev->shadow_regs[0x36] = 0x04;
 | 
						|
	      dev->shadow_regs[0x38] = 0x03;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x00;
 | 
						|
	      dev->shadow_regs[0x81] = 0x02;
 | 
						|
	      dev->shadow_regs[0x82] = 0x03;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x20;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0x00;
 | 
						|
	      dev->shadow_regs[0x88] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x00;
 | 
						|
	      dev->shadow_regs[0x92] = 0x00;
 | 
						|
	      dev->shadow_regs[0x93] = 0x06;
 | 
						|
	      break;
 | 
						|
 | 
						|
	    case A920_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x02;
 | 
						|
	      dev->shadow_regs[0x36] = 0x04;
 | 
						|
	      dev->shadow_regs[0x38] = 0x03;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x07;
 | 
						|
	      dev->shadow_regs[0x81] = 0x0f;
 | 
						|
	      dev->shadow_regs[0x82] = 0x03;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x05;
 | 
						|
	      dev->shadow_regs[0x86] = 0x14;
 | 
						|
	      dev->shadow_regs[0x87] = 0x06;
 | 
						|
	      dev->shadow_regs[0x88] = 0x44;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x60;
 | 
						|
	      dev->shadow_regs[0x92] = 0x85;
 | 
						|
	      dev->shadow_regs[0x93] = 0x0e;
 | 
						|
	      break;
 | 
						|
 | 
						|
	    case X1200_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x02;
 | 
						|
	      dev->shadow_regs[0x36] = 0x03;
 | 
						|
	      dev->shadow_regs[0x38] = 0x01;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x79] = 0x20;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x08;
 | 
						|
	      dev->shadow_regs[0x81] = 0x02;
 | 
						|
	      dev->shadow_regs[0x82] = 0x0d;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x20;
 | 
						|
	      dev->shadow_regs[0x86] = 0x1e;
 | 
						|
	      dev->shadow_regs[0x87] = 0x39;
 | 
						|
	      dev->shadow_regs[0x88] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x00;
 | 
						|
	      /* dev->shadow_regs[0x92] = 0x92; */
 | 
						|
	      dev->shadow_regs[0x93] = 0x06;
 | 
						|
	      break;
 | 
						|
 | 
						|
	    case X1200_USB2_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x04;
 | 
						|
	      dev->shadow_regs[0x36] = 0x05;
 | 
						|
	      dev->shadow_regs[0x38] = 0x04;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x01;
 | 
						|
	      dev->shadow_regs[0x81] = 0x0a;
 | 
						|
	      dev->shadow_regs[0x82] = 0x0b;
 | 
						|
	      break;
 | 
						|
	    }
 | 
						|
 | 
						|
	  dev->shadow_regs[0x35] = 0x01;
 | 
						|
	  dev->shadow_regs[0x37] = 0x01;
 | 
						|
 | 
						|
	  /* Motor enable & Coordinate space denominator */
 | 
						|
	  dev->shadow_regs[0xc3] = 0x83;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc5] = 0x0a;
 | 
						|
	  /* bounds of movement range0 */
 | 
						|
	  dev->shadow_regs[0xe0] = 0x2b;
 | 
						|
	  dev->shadow_regs[0xe1] = 0x0a;
 | 
						|
	  /* step size range0 */
 | 
						|
	  dev->shadow_regs[0xe2] = 0x7f;
 | 
						|
	  /* ? */
 | 
						|
	  dev->shadow_regs[0xe3] = 0x01;
 | 
						|
	  /* bounds of movement range1 */
 | 
						|
	  dev->shadow_regs[0xe4] = 0xbb;
 | 
						|
	  dev->shadow_regs[0xe5] = 0x09;
 | 
						|
	  /* step size range1 */
 | 
						|
	  dev->shadow_regs[0xe6] = 0x0e;
 | 
						|
	  /* bounds of movement range2 */
 | 
						|
	  dev->shadow_regs[0xe7] = 0x2b;
 | 
						|
	  dev->shadow_regs[0xe8] = 0x03;
 | 
						|
	  /* step size range2 */
 | 
						|
	  dev->shadow_regs[0xe9] = 0x05;
 | 
						|
	  /* bounds of movement range3 */
 | 
						|
	  dev->shadow_regs[0xea] = 0xa0;
 | 
						|
	  dev->shadow_regs[0xeb] = 0x01;
 | 
						|
	  /* step size range3 */
 | 
						|
	  dev->shadow_regs[0xec] = 0x01;
 | 
						|
	  /* step size range4 */
 | 
						|
	  dev->shadow_regs[0xef] = 0x01;
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  /* set grayscale  scan  */
 | 
						|
	  dev->shadow_regs[0x2f] = 0x21;
 | 
						|
	  switch (dev->model.sensor_type)
 | 
						|
	    {
 | 
						|
	    case X1100_B2_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x02;
 | 
						|
	      dev->shadow_regs[0x35] = 0x02;
 | 
						|
	      dev->shadow_regs[0x36] = 0x04;
 | 
						|
	      dev->shadow_regs[0x37] = 0x04;
 | 
						|
	      dev->shadow_regs[0x38] = 0x06;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x20;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0x00;
 | 
						|
	      dev->shadow_regs[0x88] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x00;
 | 
						|
	      dev->shadow_regs[0x92] = 0x00;
 | 
						|
	      dev->shadow_regs[0x93] = 0x06;
 | 
						|
	      break;
 | 
						|
	    case X1100_2C_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x01;
 | 
						|
	      dev->shadow_regs[0x35] = 0x01;
 | 
						|
	      dev->shadow_regs[0x36] = 0x02;
 | 
						|
	      dev->shadow_regs[0x37] = 0x02;
 | 
						|
	      dev->shadow_regs[0x38] = 0x03;	/* these are half of B2 sensor */
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x20;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0x00;
 | 
						|
	      dev->shadow_regs[0x88] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x00;
 | 
						|
	      dev->shadow_regs[0x92] = 0x00;
 | 
						|
	      dev->shadow_regs[0x92] = 0x00;
 | 
						|
	      dev->shadow_regs[0x93] = 0x06;
 | 
						|
	      break;
 | 
						|
	    case A920_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x01;
 | 
						|
	      dev->shadow_regs[0x35] = 0x01;
 | 
						|
	      dev->shadow_regs[0x36] = 0x02;
 | 
						|
	      dev->shadow_regs[0x37] = 0x02;
 | 
						|
	      dev->shadow_regs[0x38] = 0x03;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x0d;
 | 
						|
	      dev->shadow_regs[0x86] = 0x14;
 | 
						|
	      dev->shadow_regs[0x87] = 0x06;
 | 
						|
	      dev->shadow_regs[0x88] = 0x45;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x60;
 | 
						|
	      dev->shadow_regs[0x92] = 0x8d;
 | 
						|
	      dev->shadow_regs[0x93] = 0x0e;
 | 
						|
	      break;
 | 
						|
	    case X1200_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x01;
 | 
						|
	      dev->shadow_regs[0x35] = 0x01;
 | 
						|
	      dev->shadow_regs[0x36] = 0x02;
 | 
						|
	      dev->shadow_regs[0x37] = 0x02;
 | 
						|
	      dev->shadow_regs[0x38] = 0x02;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x79] = 0x20;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x00;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0xff;
 | 
						|
	      dev->shadow_regs[0x88] = 0x02;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x92] = 0x00;
 | 
						|
	      break;
 | 
						|
	    case X1200_USB2_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x01;
 | 
						|
	      dev->shadow_regs[0x35] = 0x01;
 | 
						|
	      dev->shadow_regs[0x36] = 0x02;
 | 
						|
	      dev->shadow_regs[0x37] = 0x02;
 | 
						|
	      dev->shadow_regs[0x38] = 0x02;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x79] = 0x20;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x00;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0xff;
 | 
						|
	      dev->shadow_regs[0x88] = 0x02;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x92] = 0x00;
 | 
						|
	      break;
 | 
						|
	    }
 | 
						|
 | 
						|
	  /* set ? only for colour? */
 | 
						|
	  dev->shadow_regs[0x80] = 0x00;
 | 
						|
	  dev->shadow_regs[0x81] = 0x00;
 | 
						|
	  dev->shadow_regs[0x82] = 0x00;
 | 
						|
	  /* Motor enable & Coordinate space denominator */
 | 
						|
	  dev->shadow_regs[0xc3] = 0x81;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc5] = 0x10;
 | 
						|
	  /* bounds of movement range0 */
 | 
						|
	  dev->shadow_regs[0xe0] = 0x4d;
 | 
						|
	  dev->shadow_regs[0xe1] = 0x1c;
 | 
						|
	  /* step size range0 */
 | 
						|
	  dev->shadow_regs[0xe2] = 0x71;
 | 
						|
	  /* ? */
 | 
						|
	  dev->shadow_regs[0xe3] = 0x02;
 | 
						|
	  /* bounds of movement range1 */
 | 
						|
	  dev->shadow_regs[0xe4] = 0x6d;
 | 
						|
	  dev->shadow_regs[0xe5] = 0x15;
 | 
						|
	  /* step size range1 */
 | 
						|
	  dev->shadow_regs[0xe6] = 0xdc;
 | 
						|
	  /* bounds of movement range2 */
 | 
						|
	  dev->shadow_regs[0xe7] = 0xad;
 | 
						|
	  dev->shadow_regs[0xe8] = 0x07;
 | 
						|
	  /* step size range2 */
 | 
						|
	  dev->shadow_regs[0xe9] = 0x1b;
 | 
						|
	  /* bounds of movement range3 */
 | 
						|
	  dev->shadow_regs[0xea] = 0xe1;
 | 
						|
	  dev->shadow_regs[0xeb] = 0x03;
 | 
						|
	  /* step size range3 */
 | 
						|
	  dev->shadow_regs[0xec] = 0x07;
 | 
						|
	  /* bounds of movement range4 -only for 75dpi grayscale */
 | 
						|
	  dev->shadow_regs[0xed] = 0xc2;
 | 
						|
	  dev->shadow_regs[0xee] = 0x02;
 | 
						|
	  /* step size range4 */
 | 
						|
	  dev->shadow_regs[0xef] = 0x03;
 | 
						|
	}
 | 
						|
 | 
						|
      /* set motor resolution divisor */
 | 
						|
      dev->shadow_regs[0x39] = 0x0f;
 | 
						|
      /* Movement direction & step size */
 | 
						|
      dev->shadow_regs[0xc6] = 0x09;
 | 
						|
 | 
						|
      dev->shadow_regs[0xc9] = 0x3b;
 | 
						|
      dev->shadow_regs[0xca] = 0x01;
 | 
						|
 | 
						|
      /* set # of head moves per CIS read */
 | 
						|
      rts88xx_set_scan_frequency (dev->shadow_regs, 1);
 | 
						|
      /* set horizontal resolution */
 | 
						|
      if (dev->model.sensor_type != X1200_SENSOR)
 | 
						|
	dev->shadow_regs[0x79] = 0x08;
 | 
						|
    }
 | 
						|
 | 
						|
  /* 150dpi x 150dpi */
 | 
						|
  if (yres == 150)
 | 
						|
    {
 | 
						|
      DBG (5, "sanei_lexmark_low_set_scan_regs(): 150 DPI resolution\n");
 | 
						|
 | 
						|
      if (isColourScan)
 | 
						|
	{
 | 
						|
	  /* set colour scan */
 | 
						|
	  dev->shadow_regs[0x2f] = 0x11;
 | 
						|
	  switch (dev->model.sensor_type)
 | 
						|
	    {
 | 
						|
	    case X1100_B2_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x0b;
 | 
						|
	      dev->shadow_regs[0x36] = 0x0b;
 | 
						|
	      dev->shadow_regs[0x38] = 0x0a;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x05;
 | 
						|
	      dev->shadow_regs[0x81] = 0x05;
 | 
						|
	      dev->shadow_regs[0x82] = 0x0a;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x83;
 | 
						|
	      dev->shadow_regs[0x86] = 0x7e;
 | 
						|
	      dev->shadow_regs[0x87] = 0xad;
 | 
						|
	      dev->shadow_regs[0x88] = 0x35;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0xfe;
 | 
						|
	      dev->shadow_regs[0x92] = 0xdf;
 | 
						|
	      dev->shadow_regs[0x93] = 0x0e;
 | 
						|
	      break;
 | 
						|
	    case X1100_2C_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x05;
 | 
						|
	      dev->shadow_regs[0x36] = 0x07;
 | 
						|
	      dev->shadow_regs[0x38] = 0x05;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x00;
 | 
						|
	      dev->shadow_regs[0x81] = 0x02;
 | 
						|
	      dev->shadow_regs[0x82] = 0x06;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x20;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0x00;
 | 
						|
	      dev->shadow_regs[0x88] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x00;
 | 
						|
	      dev->shadow_regs[0x92] = 0x00;
 | 
						|
	      dev->shadow_regs[0x93] = 0x06;
 | 
						|
	      break;
 | 
						|
	    case A920_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x03;
 | 
						|
	      dev->shadow_regs[0x36] = 0x08;
 | 
						|
	      dev->shadow_regs[0x38] = 0x05;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x0e;
 | 
						|
	      dev->shadow_regs[0x81] = 0x07;
 | 
						|
	      dev->shadow_regs[0x82] = 0x02;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x05;
 | 
						|
	      dev->shadow_regs[0x86] = 0x14;
 | 
						|
	      dev->shadow_regs[0x87] = 0x06;
 | 
						|
	      dev->shadow_regs[0x88] = 0x04;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0xe0;
 | 
						|
	      dev->shadow_regs[0x92] = 0x85;
 | 
						|
	      dev->shadow_regs[0x93] = 0x0e;
 | 
						|
	      break;
 | 
						|
	    case X1200_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x04;
 | 
						|
	      dev->shadow_regs[0x36] = 0x05;
 | 
						|
	      dev->shadow_regs[0x38] = 0x02;
 | 
						|
	      /* data compression
 | 
						|
	      dev->shadow_regs[0x40] = 0x90;
 | 
						|
	      dev->shadow_regs[0x50] = 0x20; */
 | 
						|
	      /* no data compression */
 | 
						|
	      dev->shadow_regs[0x40] = 0x80;
 | 
						|
	      dev->shadow_regs[0x50] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x79] = 0x20;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x00;
 | 
						|
	      dev->shadow_regs[0x81] = 0x07;
 | 
						|
	      dev->shadow_regs[0x82] = 0x0b;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x20;
 | 
						|
	      dev->shadow_regs[0x86] = 0x1e;
 | 
						|
	      dev->shadow_regs[0x87] = 0x39;
 | 
						|
	      dev->shadow_regs[0x88] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x92] = 0x92;
 | 
						|
 | 
						|
	      break;
 | 
						|
	    case X1200_USB2_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x04;
 | 
						|
	      dev->shadow_regs[0x36] = 0x05;
 | 
						|
	      dev->shadow_regs[0x38] = 0x02;
 | 
						|
	      
 | 
						|
	      dev->shadow_regs[0x40] = 0x80;
 | 
						|
	      dev->shadow_regs[0x50] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x79] = 0x20;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x00;
 | 
						|
	      dev->shadow_regs[0x81] = 0x07;
 | 
						|
	      dev->shadow_regs[0x82] = 0x0b;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x20;
 | 
						|
	      dev->shadow_regs[0x86] = 0x1e;
 | 
						|
	      dev->shadow_regs[0x87] = 0x39;
 | 
						|
	      dev->shadow_regs[0x88] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x92] = 0x92;
 | 
						|
	      break;
 | 
						|
	    }
 | 
						|
	  /* set ? */
 | 
						|
	  dev->shadow_regs[0x35] = 0x01;
 | 
						|
	  dev->shadow_regs[0x37] = 0x01;
 | 
						|
	  /* Motor enable & Coordinate space denominator */
 | 
						|
	  dev->shadow_regs[0xc3] = 0x83;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc5] = 0x0e;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc9] = 0x3a;
 | 
						|
	  dev->shadow_regs[0xca] = 0x03;
 | 
						|
	  /* bounds of movement range0 */
 | 
						|
	  dev->shadow_regs[0xe0] = 0x61;
 | 
						|
	  dev->shadow_regs[0xe1] = 0x0a;
 | 
						|
	  /* step size range0 */
 | 
						|
	  dev->shadow_regs[0xe2] = 0xed;
 | 
						|
	  /* ? */
 | 
						|
	  dev->shadow_regs[0xe3] = 0x02;
 | 
						|
	  /* bounds of movement range1 */
 | 
						|
	  dev->shadow_regs[0xe4] = 0x29;
 | 
						|
	  dev->shadow_regs[0xe5] = 0x0a;
 | 
						|
	  /* step size range1 */
 | 
						|
	  dev->shadow_regs[0xe6] = 0x0e;
 | 
						|
	  /* bounds of movement range2 */
 | 
						|
	  dev->shadow_regs[0xe7] = 0x29;
 | 
						|
	  dev->shadow_regs[0xe8] = 0x03;
 | 
						|
	  /* step size range2 */
 | 
						|
	  dev->shadow_regs[0xe9] = 0x05;
 | 
						|
	  /* bounds of movement range3 */
 | 
						|
	  dev->shadow_regs[0xea] = 0x00;
 | 
						|
	  dev->shadow_regs[0xeb] = 0x00;
 | 
						|
	  /* step size range3 */
 | 
						|
	  dev->shadow_regs[0xec] = 0x01;
 | 
						|
	  /* step size range4 */
 | 
						|
	  dev->shadow_regs[0xef] = 0x01;
 | 
						|
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  /* set grayscale  scan */
 | 
						|
	  dev->shadow_regs[0x2f] = 0x21;
 | 
						|
	  switch (dev->model.sensor_type)
 | 
						|
	    {
 | 
						|
	    case X1100_B2_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x04;
 | 
						|
	      dev->shadow_regs[0x35] = 0x04;
 | 
						|
	      dev->shadow_regs[0x36] = 0x07;
 | 
						|
	      dev->shadow_regs[0x37] = 0x07;
 | 
						|
	      dev->shadow_regs[0x38] = 0x0a;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x00;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0x00;
 | 
						|
	      dev->shadow_regs[0x88] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x00;
 | 
						|
	      dev->shadow_regs[0x92] = 0x00;
 | 
						|
	      dev->shadow_regs[0x93] = 0x06;
 | 
						|
	      break;
 | 
						|
	    case X1100_2C_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x02;
 | 
						|
	      dev->shadow_regs[0x35] = 0x02;
 | 
						|
	      dev->shadow_regs[0x36] = 0x04;
 | 
						|
	      dev->shadow_regs[0x37] = 0x04;
 | 
						|
	      dev->shadow_regs[0x38] = 0x05;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x20;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0x00;
 | 
						|
	      dev->shadow_regs[0x88] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x00;
 | 
						|
	      dev->shadow_regs[0x92] = 0x00;
 | 
						|
	      dev->shadow_regs[0x93] = 0x06;
 | 
						|
	      break;
 | 
						|
	    case A920_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x02;
 | 
						|
	      dev->shadow_regs[0x35] = 0x02;
 | 
						|
	      dev->shadow_regs[0x36] = 0x04;
 | 
						|
	      dev->shadow_regs[0x37] = 0x04;
 | 
						|
	      dev->shadow_regs[0x38] = 0x05;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x0d;
 | 
						|
	      dev->shadow_regs[0x86] = 0x14;
 | 
						|
	      dev->shadow_regs[0x87] = 0x06;
 | 
						|
	      dev->shadow_regs[0x88] = 0x45;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x60;
 | 
						|
	      dev->shadow_regs[0x92] = 0x8d;
 | 
						|
	      dev->shadow_regs[0x93] = 0x0e;
 | 
						|
	      break;
 | 
						|
	    case X1200_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x01;
 | 
						|
	      dev->shadow_regs[0x35] = 0x01;
 | 
						|
	      dev->shadow_regs[0x36] = 0x02;
 | 
						|
	      dev->shadow_regs[0x37] = 0x02;
 | 
						|
	      dev->shadow_regs[0x38] = 0x03;
 | 
						|
 | 
						|
	      /* dev->shadow_regs[0x40] = 0x90;
 | 
						|
	      dev->shadow_regs[0x50] = 0x20;*/
 | 
						|
	      /* no data compression */
 | 
						|
	      dev->shadow_regs[0x40] = 0x80;
 | 
						|
	      dev->shadow_regs[0x50] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x79] = 0x20;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x00;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0xff;
 | 
						|
	      dev->shadow_regs[0x88] = 0x02;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x92] = 0x92;
 | 
						|
	      break;
 | 
						|
	    case X1200_USB2_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x01;
 | 
						|
	      dev->shadow_regs[0x35] = 0x01;
 | 
						|
	      dev->shadow_regs[0x36] = 0x02;
 | 
						|
	      dev->shadow_regs[0x37] = 0x02;
 | 
						|
	      dev->shadow_regs[0x38] = 0x03;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x40] = 0x80;
 | 
						|
	      dev->shadow_regs[0x50] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x79] = 0x20;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x00;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0xff;
 | 
						|
	      dev->shadow_regs[0x88] = 0x02;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x92] = 0x92;
 | 
						|
	      break;
 | 
						|
	    }
 | 
						|
 | 
						|
	  /* set ? only for colour? */
 | 
						|
	  dev->shadow_regs[0x80] = 0x00;
 | 
						|
	  dev->shadow_regs[0x81] = 0x00;
 | 
						|
	  dev->shadow_regs[0x82] = 0x00;
 | 
						|
	  /* Motor enable & Coordinate space denominator */
 | 
						|
	  dev->shadow_regs[0xc3] = 0x81;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc5] = 0x16;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc9] = 0x3b;
 | 
						|
	  dev->shadow_regs[0xca] = 0x01;
 | 
						|
	  /* bounds of movement range0 */
 | 
						|
	  dev->shadow_regs[0xe0] = 0xdd;
 | 
						|
	  dev->shadow_regs[0xe1] = 0x18;
 | 
						|
	  /* step size range0 */
 | 
						|
	  dev->shadow_regs[0xe2] = 0x01;
 | 
						|
	  /* ? */
 | 
						|
	  dev->shadow_regs[0xe3] = 0x03;
 | 
						|
	  /* bounds of movement range1 */
 | 
						|
	  dev->shadow_regs[0xe4] = 0x6d;
 | 
						|
	  dev->shadow_regs[0xe5] = 0x15;
 | 
						|
	  /* step size range1 */
 | 
						|
	  dev->shadow_regs[0xe6] = 0xdc;
 | 
						|
	  /* bounds of movement range2 */
 | 
						|
	  dev->shadow_regs[0xe7] = 0xad;
 | 
						|
	  dev->shadow_regs[0xe8] = 0x07;
 | 
						|
	  /* step size range2 */
 | 
						|
	  dev->shadow_regs[0xe9] = 0x1b;
 | 
						|
	  /* bounds of movement range3 */
 | 
						|
	  dev->shadow_regs[0xea] = 0xe1;
 | 
						|
	  dev->shadow_regs[0xeb] = 0x03;
 | 
						|
	  /* step size range3 */
 | 
						|
	  dev->shadow_regs[0xec] = 0x07;
 | 
						|
	  /* step size range4 */
 | 
						|
	  dev->shadow_regs[0xef] = 0x03;
 | 
						|
	}
 | 
						|
 | 
						|
      /* set motor resolution divisor */
 | 
						|
      dev->shadow_regs[0x39] = 0x07;
 | 
						|
      /* Movement direction & step size */
 | 
						|
      dev->shadow_regs[0xc6] = 0x09;
 | 
						|
 | 
						|
      /* set # of head moves per CIS read */
 | 
						|
      rts88xx_set_scan_frequency (dev->shadow_regs, 1);
 | 
						|
 | 
						|
      /* hum, horizontal resolution different for X1200 ? */
 | 
						|
      if (dev->model.sensor_type != X1200_SENSOR)
 | 
						|
	dev->shadow_regs[0x79] = 0x20;
 | 
						|
    }
 | 
						|
 | 
						|
  /*300dpi x 300dpi */
 | 
						|
  if (yres == 300)
 | 
						|
    {
 | 
						|
      DBG (5, "sanei_lexmark_low_set_scan_regs(): 300 DPI resolution\n");
 | 
						|
 | 
						|
      if (isColourScan)
 | 
						|
	{
 | 
						|
	  /* set colour scan */
 | 
						|
	  dev->shadow_regs[0x2f] = 0x11;
 | 
						|
 | 
						|
	  switch (dev->model.sensor_type)
 | 
						|
	    {
 | 
						|
	    case X1100_B2_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x15;
 | 
						|
	      dev->shadow_regs[0x36] = 0x15;
 | 
						|
	      dev->shadow_regs[0x38] = 0x14;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x0a;
 | 
						|
	      dev->shadow_regs[0x81] = 0x0a;
 | 
						|
	      dev->shadow_regs[0x82] = 0x06;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x83;
 | 
						|
	      dev->shadow_regs[0x86] = 0x7e;
 | 
						|
	      dev->shadow_regs[0x87] = 0xad;
 | 
						|
	      dev->shadow_regs[0x88] = 0x35;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0xfe;
 | 
						|
	      dev->shadow_regs[0x92] = 0xdf;
 | 
						|
	      dev->shadow_regs[0x93] = 0x0e;
 | 
						|
	      break;
 | 
						|
	    case X1100_2C_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x08;
 | 
						|
	      dev->shadow_regs[0x36] = 0x0d;
 | 
						|
	      dev->shadow_regs[0x38] = 0x09;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x0e;
 | 
						|
	      dev->shadow_regs[0x81] = 0x04;
 | 
						|
	      dev->shadow_regs[0x82] = 0x0a;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x20;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0x00;
 | 
						|
	      dev->shadow_regs[0x88] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x00;
 | 
						|
	      dev->shadow_regs[0x92] = 0x00;
 | 
						|
	      dev->shadow_regs[0x93] = 0x06;
 | 
						|
	      break;
 | 
						|
	    case A920_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x06;
 | 
						|
	      dev->shadow_regs[0x36] = 0x10;
 | 
						|
	      dev->shadow_regs[0x38] = 0x09;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x0c;
 | 
						|
	      dev->shadow_regs[0x81] = 0x02;
 | 
						|
	      dev->shadow_regs[0x82] = 0x04;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x05;
 | 
						|
	      dev->shadow_regs[0x86] = 0x14;
 | 
						|
	      dev->shadow_regs[0x87] = 0x06;
 | 
						|
	      dev->shadow_regs[0x88] = 0x04;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0xe0;
 | 
						|
	      dev->shadow_regs[0x92] = 0x85;
 | 
						|
	      dev->shadow_regs[0x93] = 0x0e;
 | 
						|
	      break;
 | 
						|
	    case X1200_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x07;
 | 
						|
	      dev->shadow_regs[0x36] = 0x09;
 | 
						|
	      dev->shadow_regs[0x38] = 0x04;
 | 
						|
 | 
						|
	      /* data compression 
 | 
						|
	      dev->shadow_regs[0x40] = 0x90;
 | 
						|
	      dev->shadow_regs[0x50] = 0x20; */
 | 
						|
	      /* no data compression */
 | 
						|
	      dev->shadow_regs[0x40] = 0x80;
 | 
						|
	      dev->shadow_regs[0x50] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x00;
 | 
						|
	      dev->shadow_regs[0x81] = 0x0e;
 | 
						|
	      dev->shadow_regs[0x82] = 0x06;
 | 
						|
	      break;
 | 
						|
	    case X1200_USB2_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x07;
 | 
						|
	      dev->shadow_regs[0x36] = 0x09;
 | 
						|
	      dev->shadow_regs[0x38] = 0x04;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x40] = 0x80;
 | 
						|
	      dev->shadow_regs[0x50] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x00;
 | 
						|
	      dev->shadow_regs[0x81] = 0x0e;
 | 
						|
	      dev->shadow_regs[0x82] = 0x06;
 | 
						|
	      break;
 | 
						|
	    }
 | 
						|
 | 
						|
	  /* set ? */
 | 
						|
	  dev->shadow_regs[0x35] = 0x01;
 | 
						|
	  dev->shadow_regs[0x37] = 0x01;
 | 
						|
	  /* set motor resolution divisor */
 | 
						|
	  dev->shadow_regs[0x39] = 0x03;
 | 
						|
	  /* set ? */
 | 
						|
	  /* Motor enable & Coordinate space denominator */
 | 
						|
	  dev->shadow_regs[0xc3] = 0x83;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc5] = 0x17;
 | 
						|
	  /* Movement direction & step size */
 | 
						|
	  dev->shadow_regs[0xc6] = 0x09;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc9] = 0x3a;
 | 
						|
	  dev->shadow_regs[0xca] = 0x0a;
 | 
						|
	  /* bounds of movement range0 */
 | 
						|
	  dev->shadow_regs[0xe0] = 0x75;
 | 
						|
	  dev->shadow_regs[0xe1] = 0x0a;
 | 
						|
	  /* step size range0 */
 | 
						|
	  dev->shadow_regs[0xe2] = 0xdd;
 | 
						|
	  /* ? */
 | 
						|
	  dev->shadow_regs[0xe3] = 0x05;
 | 
						|
	  /* bounds of movement range1 */
 | 
						|
	  dev->shadow_regs[0xe4] = 0x59;
 | 
						|
	  dev->shadow_regs[0xe5] = 0x0a;
 | 
						|
	  /* step size range1 */
 | 
						|
	  dev->shadow_regs[0xe6] = 0x0e;
 | 
						|
	  /* bounds of movement range2 */
 | 
						|
	  dev->shadow_regs[0xe7] = 0x00;
 | 
						|
	  dev->shadow_regs[0xe8] = 0x00;
 | 
						|
	  /* step size range2 */
 | 
						|
	  dev->shadow_regs[0xe9] = 0x05;
 | 
						|
	  /* bounds of movement range3 */
 | 
						|
	  dev->shadow_regs[0xea] = 0x00;
 | 
						|
	  dev->shadow_regs[0xeb] = 0x00;
 | 
						|
	  /* step size range3 */
 | 
						|
	  dev->shadow_regs[0xec] = 0x01;
 | 
						|
	  /* step size range4 */
 | 
						|
	  dev->shadow_regs[0xef] = 0x01;
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  /* set grayscale  scan */
 | 
						|
	  dev->shadow_regs[0x2f] = 0x21;
 | 
						|
	  /* set ? */
 | 
						|
	  switch (dev->model.sensor_type)
 | 
						|
	    {
 | 
						|
	    case X1100_B2_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x08;
 | 
						|
	      dev->shadow_regs[0x35] = 0x08;
 | 
						|
	      dev->shadow_regs[0x36] = 0x0f;
 | 
						|
	      dev->shadow_regs[0x37] = 0x0f;
 | 
						|
	      dev->shadow_regs[0x38] = 0x16;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x00;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0x00;
 | 
						|
	      dev->shadow_regs[0x88] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x00;
 | 
						|
	      dev->shadow_regs[0x92] = 0x00;
 | 
						|
	      dev->shadow_regs[0x93] = 0x06;
 | 
						|
	      break;
 | 
						|
	    case X1100_2C_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x04;
 | 
						|
	      dev->shadow_regs[0x35] = 0x04;
 | 
						|
	      dev->shadow_regs[0x36] = 0x07;
 | 
						|
	      dev->shadow_regs[0x37] = 0x07;
 | 
						|
	      dev->shadow_regs[0x38] = 0x0a;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x20;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0x00;
 | 
						|
	      dev->shadow_regs[0x88] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x00;
 | 
						|
	      dev->shadow_regs[0x92] = 0x00;
 | 
						|
	      dev->shadow_regs[0x93] = 0x06;
 | 
						|
	      break;
 | 
						|
	    case A920_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x03;
 | 
						|
	      dev->shadow_regs[0x35] = 0x03;
 | 
						|
	      dev->shadow_regs[0x36] = 0x06;
 | 
						|
	      dev->shadow_regs[0x37] = 0x06;
 | 
						|
	      dev->shadow_regs[0x38] = 0x09;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x05;
 | 
						|
	      dev->shadow_regs[0x86] = 0x14;
 | 
						|
	      dev->shadow_regs[0x87] = 0x06;
 | 
						|
	      dev->shadow_regs[0x88] = 0x04;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0xe0;
 | 
						|
	      dev->shadow_regs[0x92] = 0x85;
 | 
						|
	      dev->shadow_regs[0x93] = 0x0e;
 | 
						|
	      break;
 | 
						|
	    case X1200_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x02;
 | 
						|
	      dev->shadow_regs[0x35] = 0x02;
 | 
						|
	      dev->shadow_regs[0x36] = 0x04;
 | 
						|
	      dev->shadow_regs[0x37] = 0x04;
 | 
						|
	      dev->shadow_regs[0x38] = 0x06;
 | 
						|
	      break;
 | 
						|
	    case X1200_USB2_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x02;
 | 
						|
	      dev->shadow_regs[0x35] = 0x02;
 | 
						|
	      dev->shadow_regs[0x36] = 0x04;
 | 
						|
	      dev->shadow_regs[0x37] = 0x04;
 | 
						|
	      dev->shadow_regs[0x38] = 0x06;
 | 
						|
	      break;
 | 
						|
	    }
 | 
						|
 | 
						|
	  /* set motor resolution divisor */
 | 
						|
	  dev->shadow_regs[0x39] = 0x03;
 | 
						|
	  /* set ? only for colour? */
 | 
						|
	  dev->shadow_regs[0x80] = 0x00;
 | 
						|
	  dev->shadow_regs[0x81] = 0x00;
 | 
						|
	  dev->shadow_regs[0x82] = 0x00;
 | 
						|
	  /* Motor enable & Coordinate space denominator */
 | 
						|
	  dev->shadow_regs[0xc3] = 0x81;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc5] = 0x19;
 | 
						|
	  /* Movement direction & step size */
 | 
						|
	  dev->shadow_regs[0xc6] = 0x09;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc9] = 0x3a;
 | 
						|
	  dev->shadow_regs[0xca] = 0x08;
 | 
						|
	  /* bounds of movement range0 */
 | 
						|
	  dev->shadow_regs[0xe0] = 0xe3;
 | 
						|
	  dev->shadow_regs[0xe1] = 0x18;
 | 
						|
	  /* step size range0 */
 | 
						|
	  dev->shadow_regs[0xe2] = 0x03;
 | 
						|
	  /* ? */
 | 
						|
	  dev->shadow_regs[0xe3] = 0x06;
 | 
						|
	  /* bounds of movement range1 */
 | 
						|
	  dev->shadow_regs[0xe4] = 0x2b;
 | 
						|
	  dev->shadow_regs[0xe5] = 0x17;
 | 
						|
	  /* step size range1 */
 | 
						|
	  dev->shadow_regs[0xe6] = 0xdc;
 | 
						|
	  /* bounds of movement range2 */
 | 
						|
	  dev->shadow_regs[0xe7] = 0xb3;
 | 
						|
	  dev->shadow_regs[0xe8] = 0x07;
 | 
						|
	  /* step size range2 */
 | 
						|
	  dev->shadow_regs[0xe9] = 0x1b;
 | 
						|
	  /* bounds of movement range3 */
 | 
						|
	  dev->shadow_regs[0xea] = 0x00;
 | 
						|
	  dev->shadow_regs[0xeb] = 0x00;
 | 
						|
	  /* step size range3 */
 | 
						|
	  dev->shadow_regs[0xec] = 0x07;
 | 
						|
	  /* step size range4 */
 | 
						|
	  dev->shadow_regs[0xef] = 0x03;
 | 
						|
	}
 | 
						|
 | 
						|
      /* set # of head moves per CIS read */
 | 
						|
      rts88xx_set_scan_frequency (dev->shadow_regs, 1);
 | 
						|
      /* set horizontal resolution */
 | 
						|
      dev->shadow_regs[0x79] = 0x20;
 | 
						|
    }
 | 
						|
 | 
						|
  /* 600dpi x 600dpi */
 | 
						|
  if (yres == 600)
 | 
						|
    {
 | 
						|
      DBG (5, "sanei_lexmark_low_set_scan_regs(): 600 DPI resolution\n");
 | 
						|
 | 
						|
      if (isColourScan)
 | 
						|
	{
 | 
						|
	  /* set colour scan */
 | 
						|
	  dev->shadow_regs[0x2f] = 0x11;
 | 
						|
	  /* set ? */
 | 
						|
	  switch (dev->model.sensor_type)
 | 
						|
	    {
 | 
						|
	    case X1100_B2_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x15;
 | 
						|
	      dev->shadow_regs[0x36] = 0x15;
 | 
						|
	      dev->shadow_regs[0x38] = 0x14;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x02;
 | 
						|
	      dev->shadow_regs[0x81] = 0x02;
 | 
						|
	      dev->shadow_regs[0x82] = 0x08;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x83;
 | 
						|
	      dev->shadow_regs[0x86] = 0x7e;
 | 
						|
	      dev->shadow_regs[0x87] = 0xad;
 | 
						|
	      dev->shadow_regs[0x88] = 0x35;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0xfe;
 | 
						|
	      dev->shadow_regs[0x92] = 0xdf;
 | 
						|
	      dev->shadow_regs[0x93] = 0x0e;
 | 
						|
	      break;
 | 
						|
	    case X1100_2C_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x08;
 | 
						|
	      dev->shadow_regs[0x36] = 0x0d;
 | 
						|
	      dev->shadow_regs[0x38] = 0x09;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x0e;
 | 
						|
	      dev->shadow_regs[0x81] = 0x02;
 | 
						|
	      dev->shadow_regs[0x82] = 0x0a;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x20;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0x00;
 | 
						|
	      dev->shadow_regs[0x88] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x00;
 | 
						|
	      dev->shadow_regs[0x92] = 0x00;
 | 
						|
	      dev->shadow_regs[0x93] = 0x06;
 | 
						|
	      break;
 | 
						|
	    case A920_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x06;
 | 
						|
	      dev->shadow_regs[0x36] = 0x0f;
 | 
						|
	      dev->shadow_regs[0x38] = 0x09;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x79] = 0x40;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x0e;
 | 
						|
	      dev->shadow_regs[0x81] = 0x0e;
 | 
						|
	      dev->shadow_regs[0x82] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x05;
 | 
						|
	      dev->shadow_regs[0x86] = 0x14;
 | 
						|
	      dev->shadow_regs[0x87] = 0x06;
 | 
						|
	      dev->shadow_regs[0x88] = 0x04;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x60;
 | 
						|
	      dev->shadow_regs[0x92] = 0x85;
 | 
						|
	      dev->shadow_regs[0x93] = 0x0e;
 | 
						|
	      break;
 | 
						|
	    case X1200_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x07;
 | 
						|
	      dev->shadow_regs[0x36] = 0x0a;
 | 
						|
	      dev->shadow_regs[0x38] = 0x04;
 | 
						|
 | 
						|
	      /* data compression 
 | 
						|
	      dev->shadow_regs[0x40] = 0x90;
 | 
						|
	      dev->shadow_regs[0x50] = 0x20; */
 | 
						|
 | 
						|
	      /* no data compression */
 | 
						|
	      dev->shadow_regs[0x40] = 0x80;
 | 
						|
	      dev->shadow_regs[0x50] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x02;
 | 
						|
	      dev->shadow_regs[0x81] = 0x00;
 | 
						|
	      dev->shadow_regs[0x82] = 0x06;
 | 
						|
	      break;
 | 
						|
	    case X1200_USB2_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x0d;
 | 
						|
	      dev->shadow_regs[0x36] = 0x13;
 | 
						|
	      dev->shadow_regs[0x38] = 0x10;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x04;
 | 
						|
	      dev->shadow_regs[0x81] = 0x0e;
 | 
						|
	      dev->shadow_regs[0x82] = 0x08;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x02;
 | 
						|
	      dev->shadow_regs[0x86] = 0x3b;
 | 
						|
	      dev->shadow_regs[0x87] = 0x0f;
 | 
						|
	      dev->shadow_regs[0x88] = 0x24;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x19;
 | 
						|
	      dev->shadow_regs[0x92] = 0x30;
 | 
						|
	      dev->shadow_regs[0x93] = 0x0e;
 | 
						|
	      dev->shadow_regs[0xc5] = 0x17;
 | 
						|
	      dev->shadow_regs[0xc6] = 0x09;
 | 
						|
	      dev->shadow_regs[0xca] = 0x0a;
 | 
						|
	      break;
 | 
						|
	    }
 | 
						|
	  dev->shadow_regs[0x35] = 0x01;
 | 
						|
	  dev->shadow_regs[0x37] = 0x01;
 | 
						|
 | 
						|
	  /* set motor resolution divisor */
 | 
						|
	  dev->shadow_regs[0x39] = 0x03;
 | 
						|
	  /* set # of head moves per CIS read */
 | 
						|
	  rts88xx_set_scan_frequency (dev->shadow_regs, 2);
 | 
						|
	  /* Motor enable & Coordinate space denominator */
 | 
						|
	  dev->shadow_regs[0xc3] = 0x86;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc5] = 0x27;
 | 
						|
	  /* Movement direction & step size */
 | 
						|
	  dev->shadow_regs[0xc6] = 0x0c;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc9] = 0x3a;
 | 
						|
	  dev->shadow_regs[0xca] = 0x1a;
 | 
						|
	  /* bounds of movement range0 */
 | 
						|
	  dev->shadow_regs[0xe0] = 0x57;
 | 
						|
	  dev->shadow_regs[0xe1] = 0x0a;
 | 
						|
	  /* step size range0 */
 | 
						|
	  dev->shadow_regs[0xe2] = 0xbf;
 | 
						|
	  /* ? */
 | 
						|
	  dev->shadow_regs[0xe3] = 0x05;
 | 
						|
	  /* bounds of movement range1 */
 | 
						|
	  dev->shadow_regs[0xe4] = 0x3b;
 | 
						|
	  dev->shadow_regs[0xe5] = 0x0a;
 | 
						|
	  /* step size range1 */
 | 
						|
	  dev->shadow_regs[0xe6] = 0x0e;
 | 
						|
	  /* bounds of movement range2 */
 | 
						|
	  dev->shadow_regs[0xe7] = 0x00;
 | 
						|
	  dev->shadow_regs[0xe8] = 0x00;
 | 
						|
	  /* step size range2 */
 | 
						|
	  dev->shadow_regs[0xe9] = 0x05;
 | 
						|
	  /* bounds of movement range3 */
 | 
						|
	  dev->shadow_regs[0xea] = 0x00;
 | 
						|
	  dev->shadow_regs[0xeb] = 0x00;
 | 
						|
	  /* step size range3 */
 | 
						|
	  dev->shadow_regs[0xec] = 0x01;
 | 
						|
	  /* step size range4 */
 | 
						|
	  dev->shadow_regs[0xef] = 0x01;
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  /* set grayscale  scan */
 | 
						|
	  dev->shadow_regs[0x2f] = 0x21;
 | 
						|
	  switch (dev->model.sensor_type)
 | 
						|
	    {
 | 
						|
	    case X1100_B2_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x11;
 | 
						|
	      dev->shadow_regs[0x35] = 0x11;
 | 
						|
	      dev->shadow_regs[0x36] = 0x21;
 | 
						|
	      dev->shadow_regs[0x37] = 0x21;
 | 
						|
	      dev->shadow_regs[0x38] = 0x31;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x00;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0x00;
 | 
						|
	      dev->shadow_regs[0x88] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x00;
 | 
						|
	      dev->shadow_regs[0x92] = 0x00;
 | 
						|
	      dev->shadow_regs[0x93] = 0x06;
 | 
						|
	      break;
 | 
						|
	    case X1100_2C_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x07;
 | 
						|
	      dev->shadow_regs[0x35] = 0x07;
 | 
						|
	      dev->shadow_regs[0x36] = 0x0d;
 | 
						|
	      dev->shadow_regs[0x37] = 0x0d;
 | 
						|
	      dev->shadow_regs[0x38] = 0x13;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x20;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0x00;
 | 
						|
	      dev->shadow_regs[0x88] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x00;
 | 
						|
	      dev->shadow_regs[0x92] = 0x00;
 | 
						|
	      dev->shadow_regs[0x93] = 0x06;
 | 
						|
	      break;
 | 
						|
	    case A920_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x05;
 | 
						|
	      dev->shadow_regs[0x35] = 0x05;
 | 
						|
	      dev->shadow_regs[0x36] = 0x0b;
 | 
						|
	      dev->shadow_regs[0x37] = 0x0b;
 | 
						|
	      dev->shadow_regs[0x38] = 0x11;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x05;
 | 
						|
	      dev->shadow_regs[0x86] = 0x14;
 | 
						|
	      dev->shadow_regs[0x87] = 0x06;
 | 
						|
	      dev->shadow_regs[0x88] = 0x04;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0xe0;
 | 
						|
	      dev->shadow_regs[0x92] = 0x85;
 | 
						|
	      dev->shadow_regs[0x93] = 0x0e;
 | 
						|
	      break;
 | 
						|
	    case X1200_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x03;
 | 
						|
	      dev->shadow_regs[0x35] = 0x03;
 | 
						|
	      dev->shadow_regs[0x36] = 0x07;
 | 
						|
	      dev->shadow_regs[0x37] = 0x07;
 | 
						|
	      dev->shadow_regs[0x38] = 0x0b;
 | 
						|
 | 
						|
	      /* data compression 
 | 
						|
	      dev->shadow_regs[0x40] = 0x90; 
 | 
						|
	      dev->shadow_regs[0x50] = 0x20; */
 | 
						|
	      /* no data compression */
 | 
						|
	      dev->shadow_regs[0x40] = 0x80;
 | 
						|
	      dev->shadow_regs[0x50] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x00;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0xff;
 | 
						|
	      dev->shadow_regs[0x88] = 0x02;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x92] = 0x00;
 | 
						|
 | 
						|
	      break;
 | 
						|
	    case X1200_USB2_SENSOR:
 | 
						|
	      dev->shadow_regs[0x34] = 0x03;
 | 
						|
	      dev->shadow_regs[0x35] = 0x03;
 | 
						|
	      dev->shadow_regs[0x36] = 0x07;
 | 
						|
	      dev->shadow_regs[0x37] = 0x07;
 | 
						|
	      dev->shadow_regs[0x38] = 0x0b;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x40] = 0x80;
 | 
						|
	      dev->shadow_regs[0x50] = 0x00;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x00;
 | 
						|
	      dev->shadow_regs[0x86] = 0x00;
 | 
						|
	      dev->shadow_regs[0x87] = 0xff;
 | 
						|
	      dev->shadow_regs[0x88] = 0x02;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x92] = 0x00;
 | 
						|
	      break;
 | 
						|
	    }
 | 
						|
	  /* set motor resolution divisor */
 | 
						|
	  dev->shadow_regs[0x39] = 0x01;
 | 
						|
	  /* set # of head moves per CIS read */
 | 
						|
	  rts88xx_set_scan_frequency (dev->shadow_regs, 1);
 | 
						|
 | 
						|
	  /* set ? only for colour? */
 | 
						|
	  dev->shadow_regs[0x80] = 0x00;
 | 
						|
	  dev->shadow_regs[0x81] = 0x00;
 | 
						|
	  dev->shadow_regs[0x82] = 0x00;
 | 
						|
	  /* Motor enable & Coordinate space denominator */
 | 
						|
	  dev->shadow_regs[0xc3] = 0x81;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc5] = 0x22;
 | 
						|
	  /* Movement direction & step size */
 | 
						|
	  dev->shadow_regs[0xc6] = 0x09;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc9] = 0x3b;
 | 
						|
	  dev->shadow_regs[0xca] = 0x1f;
 | 
						|
	  /* bounds of movement range0 */
 | 
						|
	  dev->shadow_regs[0xe0] = 0xf7;
 | 
						|
	  dev->shadow_regs[0xe1] = 0x16;
 | 
						|
	  /* step size range0 */
 | 
						|
	  dev->shadow_regs[0xe2] = 0x87;
 | 
						|
	  /* ? */
 | 
						|
	  dev->shadow_regs[0xe3] = 0x13;
 | 
						|
	  /* bounds of movement range1 */
 | 
						|
	  dev->shadow_regs[0xe4] = 0x1b;
 | 
						|
	  dev->shadow_regs[0xe5] = 0x16;
 | 
						|
	  /* step size range1 */
 | 
						|
	  dev->shadow_regs[0xe6] = 0xdc;
 | 
						|
	  /* bounds of movement range2 */
 | 
						|
	  dev->shadow_regs[0xe7] = 0x00;
 | 
						|
	  dev->shadow_regs[0xe8] = 0x00;
 | 
						|
	  /* step size range2 */
 | 
						|
	  dev->shadow_regs[0xe9] = 0x1b;
 | 
						|
	  /* bounds of movement range3 */
 | 
						|
	  dev->shadow_regs[0xea] = 0x00;
 | 
						|
	  dev->shadow_regs[0xeb] = 0x00;
 | 
						|
	  /* step size range3 */
 | 
						|
	  dev->shadow_regs[0xec] = 0x07;
 | 
						|
	  /* step size range4 */
 | 
						|
	  dev->shadow_regs[0xef] = 0x03;
 | 
						|
	}
 | 
						|
 | 
						|
      /* set horizontal resolution */
 | 
						|
      dev->shadow_regs[0x79] = 0x40;
 | 
						|
    }
 | 
						|
  /*600dpi x 1200dpi */
 | 
						|
  if (yres == 1200)
 | 
						|
    {
 | 
						|
      DBG (5, "sanei_lexmark_low_set_scan_regs(): 1200 DPI resolution\n");
 | 
						|
 | 
						|
      if (isColourScan)
 | 
						|
	{
 | 
						|
	  /* set colour scan */
 | 
						|
	  dev->shadow_regs[0x2f] = 0x11;
 | 
						|
	  /* set motor resolution divisor */
 | 
						|
	  dev->shadow_regs[0x39] = 0x01;
 | 
						|
	  /* set # of head moves per CIS read */
 | 
						|
	  rts88xx_set_scan_frequency (dev->shadow_regs, 2);
 | 
						|
 | 
						|
	  if (dev->model.sensor_type == X1100_B2_SENSOR)
 | 
						|
	    {
 | 
						|
	      /* set ? */
 | 
						|
	      dev->shadow_regs[0x34] = 0x29;
 | 
						|
	      dev->shadow_regs[0x36] = 0x29;
 | 
						|
	      dev->shadow_regs[0x38] = 0x28;
 | 
						|
	      /* set ? */
 | 
						|
	      dev->shadow_regs[0x80] = 0x04;
 | 
						|
	      dev->shadow_regs[0x81] = 0x04;
 | 
						|
	      dev->shadow_regs[0x82] = 0x08;
 | 
						|
	      dev->shadow_regs[0x85] = 0x83;
 | 
						|
	      dev->shadow_regs[0x86] = 0x7e;
 | 
						|
	      dev->shadow_regs[0x87] = 0xad;
 | 
						|
	      dev->shadow_regs[0x88] = 0x35;
 | 
						|
	      dev->shadow_regs[0x91] = 0xfe;
 | 
						|
	      dev->shadow_regs[0x92] = 0xdf;
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    {			/* A920 case */
 | 
						|
	      dev->shadow_regs[0x34] = 0x0c;
 | 
						|
	      dev->shadow_regs[0x36] = 0x1e;
 | 
						|
	      dev->shadow_regs[0x38] = 0x10;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x80] = 0x0c;
 | 
						|
	      dev->shadow_regs[0x81] = 0x08;
 | 
						|
	      dev->shadow_regs[0x82] = 0x0c;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x85] = 0x05;
 | 
						|
	      dev->shadow_regs[0x86] = 0x14;
 | 
						|
	      dev->shadow_regs[0x87] = 0x06;
 | 
						|
	      dev->shadow_regs[0x88] = 0x04;
 | 
						|
 | 
						|
	      dev->shadow_regs[0x91] = 0x60;
 | 
						|
	      dev->shadow_regs[0x92] = 0x85;
 | 
						|
	    }
 | 
						|
 | 
						|
	  dev->shadow_regs[0x35] = 0x01;
 | 
						|
	  dev->shadow_regs[0x37] = 0x01;
 | 
						|
	  /* set motor resolution divisor */
 | 
						|
	  dev->shadow_regs[0x39] = 0x01;
 | 
						|
	  dev->shadow_regs[0x93] = 0x0e;
 | 
						|
 | 
						|
	  /* Motor enable & Coordinate space denominator */
 | 
						|
	  dev->shadow_regs[0xc3] = 0x86;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc5] = 0x41;
 | 
						|
	  /* Movement direction & step size */
 | 
						|
	  dev->shadow_regs[0xc6] = 0x0c;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc9] = 0x3a;
 | 
						|
	  dev->shadow_regs[0xca] = 0x40;
 | 
						|
	  /* bounds of movement range0 */
 | 
						|
	  dev->shadow_regs[0xe0] = 0x00;
 | 
						|
	  dev->shadow_regs[0xe1] = 0x00;
 | 
						|
	  /* step size range0 */
 | 
						|
	  dev->shadow_regs[0xe2] = 0x85;
 | 
						|
	  /* ? */
 | 
						|
	  dev->shadow_regs[0xe3] = 0x0b;
 | 
						|
	  /* bounds of movement range1 */
 | 
						|
	  dev->shadow_regs[0xe4] = 0x00;
 | 
						|
	  dev->shadow_regs[0xe5] = 0x00;
 | 
						|
	  /* step size range1 */
 | 
						|
	  dev->shadow_regs[0xe6] = 0x0e;
 | 
						|
	  /* bounds of movement range2 */
 | 
						|
	  dev->shadow_regs[0xe7] = 0x00;
 | 
						|
	  dev->shadow_regs[0xe8] = 0x00;
 | 
						|
	  /* step size range2 */
 | 
						|
	  dev->shadow_regs[0xe9] = 0x05;
 | 
						|
	  /* bounds of movement range3 */
 | 
						|
	  dev->shadow_regs[0xea] = 0x00;
 | 
						|
	  dev->shadow_regs[0xeb] = 0x00;
 | 
						|
	  /* step size range3 */
 | 
						|
	  dev->shadow_regs[0xec] = 0x01;
 | 
						|
	  /* step size range4 */
 | 
						|
	  dev->shadow_regs[0xef] = 0x01;
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  /* set grayscale  scan */
 | 
						|
	  dev->shadow_regs[0x2f] = 0x21;
 | 
						|
	  /* set ? */
 | 
						|
	  dev->shadow_regs[0x34] = 0x22;
 | 
						|
	  dev->shadow_regs[0x35] = 0x22;
 | 
						|
	  dev->shadow_regs[0x36] = 0x42;
 | 
						|
	  dev->shadow_regs[0x37] = 0x42;
 | 
						|
	  dev->shadow_regs[0x38] = 0x62;
 | 
						|
	  /* set motor resolution divisor */
 | 
						|
	  dev->shadow_regs[0x39] = 0x01;
 | 
						|
	  /* set # of head moves per CIS read */
 | 
						|
	  rts88xx_set_scan_frequency (dev->shadow_regs, 0);
 | 
						|
 | 
						|
	  /* set ? only for colour? */
 | 
						|
	  dev->shadow_regs[0x80] = 0x00;
 | 
						|
	  dev->shadow_regs[0x81] = 0x00;
 | 
						|
	  dev->shadow_regs[0x82] = 0x00;
 | 
						|
	  dev->shadow_regs[0x85] = 0x00;
 | 
						|
	  dev->shadow_regs[0x86] = 0x00;
 | 
						|
	  dev->shadow_regs[0x87] = 0x00;
 | 
						|
	  dev->shadow_regs[0x88] = 0x00;
 | 
						|
	  dev->shadow_regs[0x91] = 0x00;
 | 
						|
	  dev->shadow_regs[0x92] = 0x00;
 | 
						|
	  dev->shadow_regs[0x93] = 0x06;
 | 
						|
	  /* Motor enable & Coordinate space denominator */
 | 
						|
	  dev->shadow_regs[0xc3] = 0x81;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc5] = 0x41;
 | 
						|
	  /* Movement direction & step size */
 | 
						|
	  dev->shadow_regs[0xc6] = 0x09;
 | 
						|
	  /*  ? */
 | 
						|
	  dev->shadow_regs[0xc9] = 0x3a;
 | 
						|
	  dev->shadow_regs[0xca] = 0x40;
 | 
						|
	  /* bounds of movement range0 */
 | 
						|
	  dev->shadow_regs[0xe0] = 0x00;
 | 
						|
	  dev->shadow_regs[0xe1] = 0x00;
 | 
						|
	  /* step size range0 */
 | 
						|
	  dev->shadow_regs[0xe2] = 0xc7;
 | 
						|
	  /* ? */
 | 
						|
	  dev->shadow_regs[0xe3] = 0x29;
 | 
						|
	  /* bounds of movement range1 */
 | 
						|
	  dev->shadow_regs[0xe4] = 0x00;
 | 
						|
	  dev->shadow_regs[0xe5] = 0x00;
 | 
						|
	  /* step size range1 */
 | 
						|
	  dev->shadow_regs[0xe6] = 0xdc;
 | 
						|
	  /* bounds of movement range2 */
 | 
						|
	  dev->shadow_regs[0xe7] = 0x00;
 | 
						|
	  dev->shadow_regs[0xe8] = 0x00;
 | 
						|
	  /* step size range2 */
 | 
						|
	  dev->shadow_regs[0xe9] = 0x1b;
 | 
						|
	  /* bounds of movement range3 */
 | 
						|
	  dev->shadow_regs[0xea] = 0x00;
 | 
						|
	  dev->shadow_regs[0xeb] = 0x00;
 | 
						|
	  /* step size range3 */
 | 
						|
	  dev->shadow_regs[0xec] = 0x07;
 | 
						|
	  /* step size range4 */
 | 
						|
	  dev->shadow_regs[0xef] = 0x03;
 | 
						|
	}
 | 
						|
 | 
						|
      /* set horizontal resolution */
 | 
						|
      dev->shadow_regs[0x79] = 0x40;
 | 
						|
    }
 | 
						|
 | 
						|
  /* is calibration has been done, we override fixed settings with detected ones */
 | 
						|
  if (calibrated)
 | 
						|
    {
 | 
						|
      /* override fixed values with ones from calibration */
 | 
						|
      if (rts88xx_is_color (dev->shadow_regs))
 | 
						|
	{
 | 
						|
	  rts88xx_set_offset (dev->shadow_regs,
 | 
						|
			      dev->offset.red,
 | 
						|
			      dev->offset.green, dev->offset.blue);
 | 
						|
	  rts88xx_set_gain (dev->shadow_regs,
 | 
						|
			    dev->gain.red, dev->gain.green, dev->gain.blue);
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  rts88xx_set_offset (dev->shadow_regs,
 | 
						|
			      dev->offset.gray,
 | 
						|
			      dev->offset.gray, dev->offset.gray);
 | 
						|
	  rts88xx_set_gain (dev->shadow_regs,
 | 
						|
			    dev->gain.gray, dev->gain.gray, dev->gain.gray);
 | 
						|
	}
 | 
						|
    }
 | 
						|
  DBG (2, "sanei_lexmark_low_set_scan_regs: end.\n");
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
SANE_Status
 | 
						|
sanei_lexmark_low_start_scan (Lexmark_Device * dev)
 | 
						|
{
 | 
						|
  SANE_Int devnum;
 | 
						|
 | 
						|
  static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 };
 | 
						|
 | 
						|
  static SANE_Byte command5_block[] = { 0x80, 0xb3, 0x00, 0x01 };
 | 
						|
 | 
						|
  SANE_Byte poll_result[3];
 | 
						|
  SANE_Byte read_result;
 | 
						|
  SANE_Bool scan_head_moving;
 | 
						|
  size_t size;
 | 
						|
 | 
						|
  devnum = dev->devnum;
 | 
						|
 | 
						|
  dev->transfer_buffer = NULL;	/* No data xferred yet */
 | 
						|
  DBG (2, "sanei_lexmark_low_start_scan:\n");
 | 
						|
 | 
						|
 | 
						|
  /* 80 b3 00 01  - poll for scanner not moving */
 | 
						|
  scan_head_moving = SANE_TRUE;
 | 
						|
  while (scan_head_moving)
 | 
						|
    {
 | 
						|
      size = 4;
 | 
						|
      low_usb_bulk_write (devnum, command5_block, &size);
 | 
						|
      size = 0x1;
 | 
						|
      low_usb_bulk_read (devnum, &read_result, &size);
 | 
						|
      if ((read_result & 0xF) == 0x0)
 | 
						|
	{
 | 
						|
	  scan_head_moving = SANE_FALSE;
 | 
						|
	}
 | 
						|
      /* F.O. Should be a timeout here so we don't hang if something breaks */
 | 
						|
#ifdef FAKE_USB
 | 
						|
      scan_head_moving = SANE_FALSE;
 | 
						|
#endif
 | 
						|
    }
 | 
						|
 | 
						|
  /* Clear C6 */
 | 
						|
  low_clr_c6 (devnum);
 | 
						|
  /* Stop the scanner */
 | 
						|
  low_stop_mvmt (devnum);
 | 
						|
 | 
						|
  /*Set regs x2 */
 | 
						|
  dev->shadow_regs[0x32] = 0x00;
 | 
						|
  low_write_all_regs (devnum, dev->shadow_regs);
 | 
						|
  dev->shadow_regs[0x32] = 0x40;
 | 
						|
  low_write_all_regs (devnum, dev->shadow_regs);
 | 
						|
 | 
						|
  /* Start Scan */
 | 
						|
  rts88xx_commit (devnum, dev->shadow_regs[0x2c]);
 | 
						|
 | 
						|
  /* We start with 0 bytes remaining to be read */
 | 
						|
  dev->bytes_remaining = 0;
 | 
						|
  /* and 0 bytes in the transfer buffer */
 | 
						|
  dev->bytes_in_buffer = 0;
 | 
						|
  dev->bytes_read = 0;
 | 
						|
 | 
						|
  /* Poll the available byte count until not 0 */
 | 
						|
  while (1)
 | 
						|
    {
 | 
						|
      size = 4;
 | 
						|
      low_usb_bulk_write (devnum, command4_block, &size);
 | 
						|
      size = 0x3;
 | 
						|
      low_usb_bulk_read (devnum, poll_result, &size);
 | 
						|
      if (!
 | 
						|
	  (poll_result[0] == 0 && poll_result[1] == 0 && poll_result[2] == 0))
 | 
						|
	{
 | 
						|
	  /* if result != 00 00 00 we got data */
 | 
						|
 | 
						|
	  /* data_size should be used to set bytes_remaining */
 | 
						|
	  /* data_size is set from sane_get_parameters () */
 | 
						|
	  dev->bytes_remaining = dev->data_size;
 | 
						|
	  /* Initialize the read buffer */
 | 
						|
	  read_buffer_init (dev, dev->params.bytes_per_line);
 | 
						|
	  return SANE_STATUS_GOOD;
 | 
						|
 | 
						|
	}
 | 
						|
      size = 4;
 | 
						|
      /* I'm not sure why the Windows driver does this - probably a timeout? */
 | 
						|
      low_usb_bulk_write (devnum, command5_block, &size);
 | 
						|
      size = 0x1;
 | 
						|
      low_usb_bulk_read (devnum, &read_result, &size);
 | 
						|
      if (read_result != 0x68)
 | 
						|
	{
 | 
						|
	  dev->bytes_remaining = 0;
 | 
						|
	  return SANE_STATUS_IO_ERROR;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_start_scan: end.\n");
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
long
 | 
						|
sanei_lexmark_low_read_scan_data (SANE_Byte * data, SANE_Int size,
 | 
						|
				    Lexmark_Device * dev)
 | 
						|
{
 | 
						|
  SANE_Bool isColourScan, isGrayScan;
 | 
						|
  static SANE_Byte command1_block[] = { 0x91, 0x00, 0xff, 0xc0 };
 | 
						|
  size_t cmd_size, xfer_request;
 | 
						|
  long bytes_read;
 | 
						|
  SANE_Bool even_byte;
 | 
						|
  SANE_Status status;
 | 
						|
  int i, k, val;
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_read_scan_data:\n");
 | 
						|
 | 
						|
  /* colour mode */
 | 
						|
  isGrayScan = SANE_FALSE;
 | 
						|
  if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0)
 | 
						|
    isColourScan = SANE_TRUE;
 | 
						|
  else
 | 
						|
    {
 | 
						|
      isColourScan = SANE_FALSE;
 | 
						|
      /* grayscale  mode */
 | 
						|
      if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) == 0)
 | 
						|
	isGrayScan = SANE_TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
  /* Check if we have a transfer buffer. Create one and fill it if we don't */
 | 
						|
  if (dev->transfer_buffer == NULL)
 | 
						|
    {
 | 
						|
      if (dev->bytes_remaining > 0)
 | 
						|
	{
 | 
						|
	  if (dev->bytes_remaining > MAX_XFER_SIZE)
 | 
						|
	    xfer_request = MAX_XFER_SIZE;
 | 
						|
	  else
 | 
						|
	    xfer_request = dev->bytes_remaining;
 | 
						|
 | 
						|
	  command1_block[2] = (SANE_Byte) (xfer_request >> 8);
 | 
						|
	  command1_block[3] = (SANE_Byte) (xfer_request & 0xFF);
 | 
						|
 | 
						|
          /* wait for data */
 | 
						|
          status = low_poll_data (dev->devnum);
 | 
						|
          if (status != SANE_STATUS_GOOD)
 | 
						|
            {
 | 
						|
              DBG (1, "sanei_lexmark_low_read_scan_data: time-out while waiting for data.\n");
 | 
						|
              return status;
 | 
						|
            }
 | 
						|
 | 
						|
	  /* Create buffer to hold the amount we will request */
 | 
						|
	  dev->transfer_buffer = (SANE_Byte *) malloc (MAX_XFER_SIZE);
 | 
						|
	  if (dev->transfer_buffer == NULL)
 | 
						|
	    return SANE_STATUS_NO_MEM;
 | 
						|
 | 
						|
	  /* Fill it */
 | 
						|
	  /* Write: 91 00 (xfer_size) */
 | 
						|
	  cmd_size = 4;
 | 
						|
	  low_usb_bulk_write (dev->devnum, command1_block, &cmd_size);
 | 
						|
 | 
						|
	  /* Read: xfer_size  bytes */
 | 
						|
	  cmd_size = xfer_request;
 | 
						|
	  low_usb_bulk_read (dev->devnum, dev->transfer_buffer, &cmd_size);
 | 
						|
 | 
						|
	  /* apply shading coefficients */
 | 
						|
	  k = dev->bytes_read % dev->read_buffer->linesize;
 | 
						|
	  for (i = 0; i < (int) cmd_size; i++)
 | 
						|
	    {
 | 
						|
	      val = dev->transfer_buffer[i];
 | 
						|
	      val = (int) ((float) val * dev->shading_coeff[k] + 0.5);
 | 
						|
	      if (val > 255)
 | 
						|
		val = 255;
 | 
						|
	      dev->transfer_buffer[i] = val;
 | 
						|
	      k++;
 | 
						|
	      if ((size_t) k == dev->read_buffer->linesize)
 | 
						|
		k = 0;
 | 
						|
	    }
 | 
						|
 | 
						|
	  /* advance by the amount actually read from device */
 | 
						|
	  dev->bytes_read += cmd_size;
 | 
						|
	  dev->bytes_remaining -= cmd_size;
 | 
						|
	  dev->bytes_in_buffer = cmd_size;
 | 
						|
	  dev->read_pointer = dev->transfer_buffer;
 | 
						|
	  DBG (2, "sanei_lexmark_low_read_scan_data:\n");
 | 
						|
	  DBG (2, "   Filled a buffer from the scanner\n");
 | 
						|
	  DBG (2, "   bytes_remaining: %lu\n", (u_long) dev->bytes_remaining);
 | 
						|
	  DBG (2, "   bytes_in_buffer: %lu\n", (u_long) dev->bytes_in_buffer);
 | 
						|
	  DBG (2, "   read_pointer: %p\n", dev->read_pointer);
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  DBG (5, "READ BUFFER INFO: \n");
 | 
						|
  DBG (5, "   write ptr:     %p\n", dev->read_buffer->writeptr);
 | 
						|
  DBG (5, "   read ptr:      %p\n", dev->read_buffer->readptr);
 | 
						|
  DBG (5, "   max write ptr: %p\n", dev->read_buffer->max_writeptr);
 | 
						|
  DBG (5, "   buffer size:   %lu\n", (u_long) dev->read_buffer->size);
 | 
						|
  DBG (5, "   line size:     %lu\n", (u_long) dev->read_buffer->linesize);
 | 
						|
  DBG (5, "   empty:         %d\n", dev->read_buffer->empty);
 | 
						|
  DBG (5, "   line no:       %d\n", dev->read_buffer->image_line_no);
 | 
						|
 | 
						|
 | 
						|
  /* If there is space in the read buffer, copy the transfer buffer over */
 | 
						|
  if (read_buffer_bytes_available (dev->read_buffer) >= dev->bytes_in_buffer)
 | 
						|
    {
 | 
						|
      even_byte = SANE_TRUE;
 | 
						|
      while (dev->bytes_in_buffer)
 | 
						|
	{
 | 
						|
 | 
						|
	  /* Colour Scan */
 | 
						|
	  if (isColourScan)
 | 
						|
	    {
 | 
						|
	      if (even_byte)
 | 
						|
		read_buffer_add_byte (dev->read_buffer,
 | 
						|
				      dev->read_pointer + 1);
 | 
						|
	      else
 | 
						|
		read_buffer_add_byte (dev->read_buffer,
 | 
						|
				      dev->read_pointer - 1);
 | 
						|
	      even_byte = !even_byte;
 | 
						|
	    }
 | 
						|
	  /* Gray Scan */
 | 
						|
	  else if (isGrayScan)
 | 
						|
	    {
 | 
						|
	      if (even_byte)
 | 
						|
		read_buffer_add_byte_gray (dev->read_buffer,
 | 
						|
					   dev->read_pointer + 1);
 | 
						|
	      else
 | 
						|
		read_buffer_add_byte_gray (dev->read_buffer,
 | 
						|
					   dev->read_pointer - 1);
 | 
						|
	      even_byte = !even_byte;
 | 
						|
	    }
 | 
						|
	  /* Lineart Scan */
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      if (even_byte)
 | 
						|
		read_buffer_add_bit_lineart (dev->read_buffer,
 | 
						|
					     dev->read_pointer + 1,
 | 
						|
					     dev->threshold);
 | 
						|
	      else
 | 
						|
		read_buffer_add_bit_lineart (dev->read_buffer,
 | 
						|
					     dev->read_pointer - 1,
 | 
						|
					     dev->threshold);
 | 
						|
	      even_byte = !even_byte;
 | 
						|
	    }
 | 
						|
	  dev->read_pointer = dev->read_pointer + sizeof (SANE_Byte);
 | 
						|
	  dev->bytes_in_buffer--;
 | 
						|
	}
 | 
						|
      /* free the transfer buffer */
 | 
						|
      free (dev->transfer_buffer);
 | 
						|
      dev->transfer_buffer = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
  DBG (5, "READ BUFFER INFO: \n");
 | 
						|
  DBG (5, "   write ptr:     %p\n", dev->read_buffer->writeptr);
 | 
						|
  DBG (5, "   read ptr:      %p\n", dev->read_buffer->readptr);
 | 
						|
  DBG (5, "   max write ptr: %p\n", dev->read_buffer->max_writeptr);
 | 
						|
  DBG (5, "   buffer size:   %lu\n", (u_long) dev->read_buffer->size);
 | 
						|
  DBG (5, "   line size:     %lu\n", (u_long) dev->read_buffer->linesize);
 | 
						|
  DBG (5, "   empty:         %d\n", dev->read_buffer->empty);
 | 
						|
  DBG (5, "   line no:       %d\n", dev->read_buffer->image_line_no);
 | 
						|
 | 
						|
  /* Read blocks out of read buffer */
 | 
						|
  bytes_read = read_buffer_get_bytes (dev->read_buffer, data, size);
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_read_scan_data:\n");
 | 
						|
  DBG (2, "    Copying lines from buffer to data\n");
 | 
						|
  DBG (2, "    bytes_remaining: %lu\n", (u_long) dev->bytes_remaining);
 | 
						|
  DBG (2, "    bytes_in_buffer: %lu\n", (u_long) dev->bytes_in_buffer);
 | 
						|
  DBG (2, "    read_pointer: %p\n", dev->read_buffer->readptr);
 | 
						|
  DBG (2, "    bytes_read %lu\n", (u_long) bytes_read);
 | 
						|
 | 
						|
  /* if no more bytes to xfer and read buffer empty we're at the end */
 | 
						|
  if ((dev->bytes_remaining == 0) && read_buffer_is_empty (dev->read_buffer))
 | 
						|
    {
 | 
						|
      if (!dev->eof)
 | 
						|
	{
 | 
						|
	  DBG (2,
 | 
						|
	       "sanei_lexmark_low_read_scan_data: EOF- parking the scanner\n");
 | 
						|
	  dev->eof = SANE_TRUE;
 | 
						|
	  low_rewind (dev, dev->shadow_regs);
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  DBG (2, "ERROR: Why are we trying to set eof more than once?\n");
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_read_scan_data: end.\n");
 | 
						|
  return bytes_read;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
low_rewind (Lexmark_Device * dev, SANE_Byte * regs)
 | 
						|
{
 | 
						|
  SANE_Int new_location;
 | 
						|
  SANE_Int location;
 | 
						|
  SANE_Int scale;
 | 
						|
 | 
						|
  DBG (2, "low_rewind: \n");
 | 
						|
 | 
						|
  /* We rewind at 1200dpi resolution. We rely on content of shadow registers
 | 
						|
     to compute the number of lines at 1200 dpi to go back */
 | 
						|
 | 
						|
  /* first move to start of scanning area */
 | 
						|
  scale = 600 / dev->val[OPT_RESOLUTION].w;
 | 
						|
  new_location = ((dev->val[OPT_BR_Y].w / scale) * scale) * 2;
 | 
						|
 | 
						|
  /* then add distance to go to the "origin dot" */
 | 
						|
  if (rts88xx_is_color (regs))
 | 
						|
    new_location += 400;
 | 
						|
  else
 | 
						|
    new_location += 420;
 | 
						|
 | 
						|
  location = new_location - 1;
 | 
						|
  DBG (2, "low_rewind: %d=>new_location=%d\n", dev->val[OPT_BR_Y].w,
 | 
						|
       new_location);
 | 
						|
 | 
						|
  /* stops any pending scan */
 | 
						|
  low_clr_c6 (dev->devnum);
 | 
						|
  low_cancel (dev->devnum);
 | 
						|
 | 
						|
  /* set regs for rewind */
 | 
						|
  regs[0x2f] = 0xa1;
 | 
						|
  regs[0x32] = 0x00;
 | 
						|
  regs[0x39] = 0x00;
 | 
						|
 | 
						|
  /* all other regs are always the same. these ones change with parameters */
 | 
						|
  /* the following 4 regs are the location 61,60 and the location+1 63,62 */
 | 
						|
 | 
						|
  regs[0x60] = LOBYTE (location);
 | 
						|
  regs[0x61] = HIBYTE (location);
 | 
						|
  regs[0x62] = LOBYTE (new_location);
 | 
						|
  regs[0x63] = HIBYTE (new_location);
 | 
						|
 | 
						|
/* set regs for rewind */
 | 
						|
  regs[0x79] = 0x40;
 | 
						|
  regs[0xb2] = 0x04;
 | 
						|
  regs[0xc3] = 0x81;
 | 
						|
  regs[0xc6] = 0x01;
 | 
						|
  regs[0xc9] = 0x3b;
 | 
						|
  regs[0xe0] = 0x2b;
 | 
						|
  regs[0xe1] = 0x17;
 | 
						|
  regs[0xe2] = 0xe7;
 | 
						|
  regs[0xe3] = 0x03;
 | 
						|
  regs[0xe6] = 0xdc;
 | 
						|
  regs[0xe7] = 0xb3;
 | 
						|
  regs[0xe8] = 0x07;
 | 
						|
  regs[0xe9] = 0x1b;
 | 
						|
  regs[0xea] = 0x00;
 | 
						|
  regs[0xeb] = 0x00;
 | 
						|
  regs[0xec] = 0x07;
 | 
						|
  regs[0xef] = 0x03;
 | 
						|
 | 
						|
  /* starts scan */
 | 
						|
  low_start_scan (dev->devnum, regs);
 | 
						|
  DBG (2, "low_rewind: end.\n");
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
SANE_Status
 | 
						|
read_buffer_init (Lexmark_Device * dev, int bytesperline)
 | 
						|
{
 | 
						|
  size_t no_lines_in_buffer;
 | 
						|
 | 
						|
  DBG (2, "read_buffer_init: Start\n");
 | 
						|
 | 
						|
  dev->read_buffer = (Read_Buffer *) malloc (sizeof (Read_Buffer));
 | 
						|
  if (dev->read_buffer == NULL)
 | 
						|
    return SANE_STATUS_NO_MEM;
 | 
						|
  dev->read_buffer->linesize = bytesperline;
 | 
						|
  dev->read_buffer->gray_offset = 0;
 | 
						|
  dev->read_buffer->max_gray_offset = bytesperline - 1;
 | 
						|
  dev->read_buffer->region = RED;
 | 
						|
  dev->read_buffer->red_offset = 0;
 | 
						|
  dev->read_buffer->green_offset = 1;
 | 
						|
  dev->read_buffer->blue_offset = 2;
 | 
						|
  dev->read_buffer->max_red_offset = bytesperline - 3;
 | 
						|
  dev->read_buffer->max_green_offset = bytesperline - 2;
 | 
						|
  dev->read_buffer->max_blue_offset = bytesperline - 1;
 | 
						|
  no_lines_in_buffer = 3 * MAX_XFER_SIZE / bytesperline;
 | 
						|
  dev->read_buffer->size = bytesperline * no_lines_in_buffer;
 | 
						|
  dev->read_buffer->data = (SANE_Byte *) malloc (dev->read_buffer->size);
 | 
						|
  if (dev->read_buffer->data == NULL)
 | 
						|
    return SANE_STATUS_NO_MEM;
 | 
						|
  dev->read_buffer->readptr = dev->read_buffer->data;
 | 
						|
  dev->read_buffer->writeptr = dev->read_buffer->data;
 | 
						|
  dev->read_buffer->max_writeptr = dev->read_buffer->data +
 | 
						|
    (no_lines_in_buffer - 1) * bytesperline;
 | 
						|
  dev->read_buffer->empty = SANE_TRUE;
 | 
						|
  dev->read_buffer->image_line_no = 0;
 | 
						|
  dev->read_buffer->bit_counter = 0;
 | 
						|
  dev->read_buffer->max_lineart_offset = dev->params.pixels_per_line - 1;
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
SANE_Status
 | 
						|
read_buffer_free (Read_Buffer * read_buffer)
 | 
						|
{
 | 
						|
  DBG (2, "read_buffer_free:\n");
 | 
						|
  if (read_buffer)
 | 
						|
    {
 | 
						|
      free (read_buffer->data);
 | 
						|
      free (read_buffer);
 | 
						|
      read_buffer = NULL;
 | 
						|
    }
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
size_t
 | 
						|
read_buffer_bytes_available (Read_Buffer * rb)
 | 
						|
{
 | 
						|
 | 
						|
  DBG (2, "read_buffer_bytes_available:\n");
 | 
						|
 | 
						|
  if (rb->empty)
 | 
						|
    return rb->size;
 | 
						|
  else if ((size_t) abs (rb->writeptr - rb->readptr) < rb->linesize)
 | 
						|
    return 0;			/* ptrs are less than one line apart */
 | 
						|
  else if (rb->writeptr < rb->readptr)
 | 
						|
    return (rb->readptr - rb->writeptr - rb->linesize);
 | 
						|
  else
 | 
						|
    return (rb->size + rb->readptr - rb->writeptr - rb->linesize);
 | 
						|
}
 | 
						|
 | 
						|
SANE_Status
 | 
						|
read_buffer_add_byte (Read_Buffer * rb, SANE_Byte * byte_pointer)
 | 
						|
{
 | 
						|
 | 
						|
  /* DBG(2, "read_buffer_add_byte:\n"); */
 | 
						|
  /* F.O. Need to fix the endian byte ordering here */
 | 
						|
 | 
						|
  switch (rb->region)
 | 
						|
    {
 | 
						|
    case RED:
 | 
						|
      *(rb->writeptr + rb->red_offset) = *byte_pointer;
 | 
						|
      if (rb->red_offset == rb->max_red_offset)
 | 
						|
	{
 | 
						|
	  rb->red_offset = 0;
 | 
						|
	  rb->region = GREEN;
 | 
						|
	}
 | 
						|
      else
 | 
						|
	rb->red_offset = rb->red_offset + (3 * sizeof (SANE_Byte));
 | 
						|
      return SANE_STATUS_GOOD;
 | 
						|
    case GREEN:
 | 
						|
      *(rb->writeptr + rb->green_offset) = *byte_pointer;
 | 
						|
      if (rb->green_offset == rb->max_green_offset)
 | 
						|
	{
 | 
						|
	  rb->green_offset = 1;
 | 
						|
	  rb->region = BLUE;
 | 
						|
	}
 | 
						|
      else
 | 
						|
	rb->green_offset = rb->green_offset + (3 * sizeof (SANE_Byte));
 | 
						|
      return SANE_STATUS_GOOD;
 | 
						|
    case BLUE:
 | 
						|
      *(rb->writeptr + rb->blue_offset) = *byte_pointer;
 | 
						|
      if (rb->blue_offset == rb->max_blue_offset)
 | 
						|
	{
 | 
						|
	  rb->image_line_no++;
 | 
						|
	  /* finished a line. read_buffer no longer empty */
 | 
						|
	  rb->empty = SANE_FALSE;
 | 
						|
	  rb->blue_offset = 2;
 | 
						|
	  rb->region = RED;
 | 
						|
	  if (rb->writeptr == rb->max_writeptr)
 | 
						|
	    rb->writeptr = rb->data;	/* back to beginning of buffer */
 | 
						|
	  else
 | 
						|
	    rb->writeptr = rb->writeptr + rb->linesize;	/* next line */
 | 
						|
	}
 | 
						|
      else
 | 
						|
	rb->blue_offset = rb->blue_offset + (3 * sizeof (SANE_Byte));
 | 
						|
      return SANE_STATUS_GOOD;
 | 
						|
    }
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
SANE_Status
 | 
						|
read_buffer_add_byte_gray (Read_Buffer * rb, SANE_Byte * byte_pointer)
 | 
						|
{
 | 
						|
 | 
						|
  /*  DBG(2, "read_buffer_add_byte_gray:\n"); */
 | 
						|
 | 
						|
  *(rb->writeptr + rb->gray_offset) = *byte_pointer;
 | 
						|
 | 
						|
  if (rb->gray_offset == rb->max_gray_offset)
 | 
						|
    {
 | 
						|
      rb->image_line_no++;
 | 
						|
      /* finished a line. read_buffer no longer empty */
 | 
						|
      rb->empty = SANE_FALSE;
 | 
						|
      rb->gray_offset = 0;
 | 
						|
 | 
						|
      if (rb->writeptr == rb->max_writeptr)
 | 
						|
	rb->writeptr = rb->data;	/* back to beginning of buffer */
 | 
						|
      else
 | 
						|
	rb->writeptr = rb->writeptr + rb->linesize;	/* next line */
 | 
						|
    }
 | 
						|
  else
 | 
						|
    rb->gray_offset = rb->gray_offset + (1 * sizeof (SANE_Byte));
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
SANE_Status
 | 
						|
read_buffer_add_bit_lineart (Read_Buffer * rb, SANE_Byte * byte_pointer,
 | 
						|
			     SANE_Byte threshold)
 | 
						|
{
 | 
						|
  SANE_Byte tmpByte;
 | 
						|
  SANE_Byte *currentBytePtr;
 | 
						|
  SANE_Int bitIndex;
 | 
						|
 | 
						|
  /*  DBG(2, "read_buffer_add_bit_lineart:\n"); */
 | 
						|
 | 
						|
  /* threshold = 0x80;  */
 | 
						|
  tmpByte = 0;
 | 
						|
  /* Create a bit by comparing incoming byte to threshold */
 | 
						|
  if (*byte_pointer <= threshold)
 | 
						|
    {
 | 
						|
      tmpByte = 128;
 | 
						|
    }
 | 
						|
 | 
						|
  /* Calculate the bit index in the current byte */
 | 
						|
  bitIndex = rb->bit_counter % 8;
 | 
						|
  /* Move the bit to its correct position in the temporary byte */
 | 
						|
  tmpByte = tmpByte >> bitIndex;
 | 
						|
  /* Get the pointer to the current byte */
 | 
						|
  currentBytePtr = rb->writeptr + rb->gray_offset;
 | 
						|
 | 
						|
  /* If this is the first write to this byte, clear the byte */
 | 
						|
  if (bitIndex == 0)
 | 
						|
    *currentBytePtr = 0;
 | 
						|
  /* Set the value of the bit in the current byte */
 | 
						|
  *currentBytePtr = *currentBytePtr | tmpByte;
 | 
						|
 | 
						|
  /* last bit in the line? */
 | 
						|
  if (rb->bit_counter == rb->max_lineart_offset)
 | 
						|
    {
 | 
						|
      /* Check if we're at the last byte of the line - error if not */
 | 
						|
      if (rb->gray_offset != rb->max_gray_offset)
 | 
						|
	{
 | 
						|
	  DBG (5, "read_buffer_add_bit_lineart:\n");
 | 
						|
	  DBG (5, "  Last bit of line is not last byte.\n");
 | 
						|
	  DBG (5, "  Bit Index: %d, Byte Index: %d. \n", rb->bit_counter,
 | 
						|
	       rb->max_gray_offset);
 | 
						|
	  return SANE_STATUS_INVAL;
 | 
						|
	}
 | 
						|
      rb->image_line_no++;
 | 
						|
      /* line finished read_buffer no longer empty */
 | 
						|
      rb->empty = SANE_FALSE;
 | 
						|
      rb->gray_offset = 0;
 | 
						|
      /* are we at the last line in the read buffer ? */
 | 
						|
      if (rb->writeptr == rb->max_writeptr)
 | 
						|
	rb->writeptr = rb->data;	/* back to beginning of buffer */
 | 
						|
      else
 | 
						|
	rb->writeptr = rb->writeptr + rb->linesize;	/* next line */
 | 
						|
      /* clear the bit counter */
 | 
						|
      rb->bit_counter = 0;
 | 
						|
    }
 | 
						|
  /* last bit in the byte? */
 | 
						|
  else if (bitIndex == 7)
 | 
						|
    {
 | 
						|
      /* Not at the end of the line, but byte done. Increment byte offset */
 | 
						|
      rb->gray_offset = rb->gray_offset + (1 * sizeof (SANE_Byte));
 | 
						|
      /* increment bit counter */
 | 
						|
      rb->bit_counter++;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      /* else increment bit counter */
 | 
						|
      rb->bit_counter++;
 | 
						|
    }
 | 
						|
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
size_t
 | 
						|
read_buffer_get_bytes (Read_Buffer * rb, SANE_Byte * buffer, size_t rqst_size)
 | 
						|
{
 | 
						|
  /* Read_Buffer *rb; */
 | 
						|
  size_t available_bytes;
 | 
						|
 | 
						|
  /* rb = read_buffer; */
 | 
						|
  if (rb->empty)
 | 
						|
    return 0;
 | 
						|
  else if (rb->writeptr > rb->readptr)
 | 
						|
    {
 | 
						|
      available_bytes = rb->writeptr - rb->readptr;
 | 
						|
      if (available_bytes <= rqst_size)
 | 
						|
	{
 | 
						|
	  /* We can read from the read pointer up to the write pointer */
 | 
						|
	  memcpy (buffer, rb->readptr, available_bytes);
 | 
						|
	  rb->readptr = rb->writeptr;
 | 
						|
	  rb->empty = SANE_TRUE;
 | 
						|
	  return available_bytes;
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  /* We can read from the full request size */
 | 
						|
	  memcpy (buffer, rb->readptr, rqst_size);
 | 
						|
	  rb->readptr = rb->readptr + rqst_size;
 | 
						|
	  return rqst_size;
 | 
						|
	}
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      /* The read pointer is ahead of the write pointer. Its wrapped around. */
 | 
						|
      /* We can read to the end of the buffer and make a recursive call to */
 | 
						|
      /* read any available lines at the beginning of the buffer */
 | 
						|
      available_bytes = rb->data + rb->size - rb->readptr;
 | 
						|
      if (available_bytes <= rqst_size)
 | 
						|
	{
 | 
						|
	  /* We can read from the read pointer up to the end of the buffer */
 | 
						|
	  memcpy (buffer, rb->readptr, available_bytes);
 | 
						|
	  rb->readptr = rb->data;
 | 
						|
	  if (rb->writeptr == rb->readptr)
 | 
						|
	    rb->empty = SANE_TRUE;
 | 
						|
	  return available_bytes +
 | 
						|
	    read_buffer_get_bytes (rb, buffer + available_bytes,
 | 
						|
				   rqst_size - available_bytes);
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  /* We can read from the full request size */
 | 
						|
	  memcpy (buffer, rb->readptr, rqst_size);
 | 
						|
	  rb->readptr = rb->readptr + rqst_size;
 | 
						|
	  return rqst_size;
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
SANE_Bool
 | 
						|
read_buffer_is_empty (Read_Buffer * read_buffer)
 | 
						|
{
 | 
						|
  return read_buffer->empty;
 | 
						|
}
 | 
						|
 | 
						|
/* 
 | 
						|
 * average a width*height rgb/monochrome area
 | 
						|
 * return values in given pointers
 | 
						|
 */
 | 
						|
static int
 | 
						|
average_area (SANE_Byte * regs, SANE_Byte * data, int width, int height,
 | 
						|
	      int *ra, int *ga, int *ba)
 | 
						|
{
 | 
						|
  int x, y;
 | 
						|
  int global = 0;
 | 
						|
  int rc, gc, bc;
 | 
						|
 | 
						|
  *ra = 0;
 | 
						|
  *ga = 0;
 | 
						|
  *ba = 0;
 | 
						|
  rc = 0;
 | 
						|
  gc = 0;
 | 
						|
  bc = 0;
 | 
						|
  if (rts88xx_is_color (regs))
 | 
						|
    {
 | 
						|
      for (x = 0; x < width; x++)
 | 
						|
	for (y = 0; y < height; y++)
 | 
						|
	  {
 | 
						|
	    rc += data[3 * width * y + x];
 | 
						|
	    gc += data[3 * width * y + width + x];
 | 
						|
	    bc += data[3 * width * y + 2 * width + x];
 | 
						|
	  }
 | 
						|
      global = (rc + gc + bc) / (3 * width * height);
 | 
						|
      *ra = rc / (width * height);
 | 
						|
      *ga = gc / (width * height);
 | 
						|
      *ba = bc / (width * height);
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      for (x = 0; x < width; x++)
 | 
						|
	for (y = 0; y < height; y++)
 | 
						|
	  {
 | 
						|
	    gc += data[width * y + x];
 | 
						|
	  }
 | 
						|
      global = gc / (width * height);
 | 
						|
      *ga = gc / (width * height);
 | 
						|
    }
 | 
						|
  DBG (7, "average_area: global=%d, red=%d, green=%d, blue=%d\n", global, *ra,
 | 
						|
       *ga, *ba);
 | 
						|
  return global;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * we scan a dark area with gain minimum to detect offset
 | 
						|
 */
 | 
						|
SANE_Status
 | 
						|
sanei_lexmark_low_offset_calibration (Lexmark_Device * dev)
 | 
						|
{
 | 
						|
  SANE_Byte regs[255];		/* we have our own copy of shadow registers */
 | 
						|
  SANE_Status status = SANE_STATUS_GOOD;
 | 
						|
  int i, lines = 8, yoffset = 2;
 | 
						|
  int pixels;
 | 
						|
  int failed=0;
 | 
						|
  /* offsets */
 | 
						|
  int ro = 0, go = 0, bo = 0;
 | 
						|
  /* averages */
 | 
						|
  int ra, ga, ba, average;
 | 
						|
  SANE_Byte *data = NULL;
 | 
						|
  SANE_Byte top[OFFSET_RANGES] = { 0, 0x7f, 0x9f, 0xbf, 0xff };
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
  char title[20];
 | 
						|
#endif
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_offset_calibration: start\n");
 | 
						|
  /* copy registers */
 | 
						|
  for (i = 0; i < 255; i++)
 | 
						|
    regs[i] = dev->shadow_regs[i];
 | 
						|
 | 
						|
  /* we clear movement bit */
 | 
						|
  regs[0xc3] = regs[0xc3] & 0x7f;
 | 
						|
 | 
						|
  pixels =
 | 
						|
    (dev->sensor->offset_endx - dev->sensor->offset_startx) / regs[0x7a];
 | 
						|
 | 
						|
  /* there are 4 ranges of offset:
 | 
						|
     00-7F : almost no offset
 | 
						|
     80-9F : high noise
 | 
						|
     A0-BF : high noise
 | 
						|
     C0-FF : high noise
 | 
						|
     we start with the highest one and decrease until
 | 
						|
     overall offset is ok
 | 
						|
     First loop may have such an high offset that scanned data overflow
 | 
						|
     and gives a low average. So we allways skip its results
 | 
						|
   */
 | 
						|
 | 
						|
  /* minimal gains */
 | 
						|
  DBG (3,
 | 
						|
       "sanei_lexmark_low_offset_calibration: setting gains to (1,1,1).\n");
 | 
						|
  rts88xx_set_gain (regs, 1, 1, 1);
 | 
						|
 | 
						|
  i = OFFSET_RANGES;
 | 
						|
  average = 255;
 | 
						|
 | 
						|
  /* loop on ranges until one fits. Then adjust offset, first loop is
 | 
						|
   * always done. TODO detect overflow by 'noise looking' data pattern */
 | 
						|
  while (((i > 0) && (average > dev->sensor->offset_threshold))
 | 
						|
	 || (i == OFFSET_RANGES))
 | 
						|
    {
 | 
						|
      /* next range  */
 | 
						|
      i--;
 | 
						|
 | 
						|
      /* sets to top of range */
 | 
						|
      ro = top[i];
 | 
						|
      go = top[i];
 | 
						|
      bo = top[i];
 | 
						|
      rts88xx_set_offset (regs, ro, ro, ro);
 | 
						|
      DBG (3,
 | 
						|
	   "sanei_lexmark_low_offset_calibration: setting offsets to (%d,%d,%d).\n",
 | 
						|
	   ro, ro, ro);
 | 
						|
 | 
						|
      status =
 | 
						|
	low_simple_scan (dev, regs, dev->sensor->offset_startx, pixels,
 | 
						|
			   yoffset, lines, &data);
 | 
						|
      if (status != SANE_STATUS_GOOD)
 | 
						|
	{
 | 
						|
	  DBG (1,
 | 
						|
	       "sanei_lexmark_low_offset_calibration: low_simple_scan failed!\n");
 | 
						|
	  if (data != NULL)
 | 
						|
	    free (data);
 | 
						|
	  return status;
 | 
						|
	}
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
      sprintf (title, "offset%02x.pnm", ro);
 | 
						|
      write_pnm_file(title,pixels,lines,rts88xx_is_color (regs),data);
 | 
						|
#endif
 | 
						|
      average = average_area (regs, data, pixels, lines, &ra, &ga, &ba);
 | 
						|
    }
 | 
						|
  if (i == 0)
 | 
						|
    {
 | 
						|
      DBG (2, "sanei_lexmark_low_offset_calibration: failed !\n");
 | 
						|
      failed=1;
 | 
						|
    }
 | 
						|
 | 
						|
  /* increase gain and scan again */
 | 
						|
  /* increase gain for fine offset tuning */
 | 
						|
  rts88xx_set_gain (regs, 6, 6, 6);
 | 
						|
  status =
 | 
						|
    low_simple_scan (dev, regs, dev->sensor->offset_startx, pixels, yoffset,
 | 
						|
		       lines, &data);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    {
 | 
						|
      DBG (1,
 | 
						|
	   "sanei_lexmark_low_offset_calibration: low_simple_scan failed!\n");
 | 
						|
      if (data != NULL)
 | 
						|
	free (data);
 | 
						|
      return status;
 | 
						|
    }
 | 
						|
  average = average_area (regs, data, pixels, lines, &ra, &ga, &ba);
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
  write_pnm_file("offset-final.pnm",pixels,lines,rts88xx_is_color (regs),data);
 | 
						|
#endif
 | 
						|
 | 
						|
  /* this "law" is a guess, may (should?) be changed ... */
 | 
						|
  if(!failed)
 | 
						|
  {
 | 
						|
	  if (ro > ra)
 | 
						|
		  dev->offset.red = ro - ra;
 | 
						|
	  if (go > ga)
 | 
						|
	  {
 | 
						|
      	dev->offset.green = go - ga;
 | 
						|
      	dev->offset.gray = go - ga;
 | 
						|
	  }
 | 
						|
	  if (bo > ba)
 | 
						|
		  dev->offset.blue = bo - ba;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
	  dev->offset.red=dev->sensor->offset_fallback;
 | 
						|
	  dev->offset.green=dev->sensor->offset_fallback;
 | 
						|
	  dev->offset.blue=dev->sensor->offset_fallback;
 | 
						|
  }
 | 
						|
  DBG (7,
 | 
						|
       "sanei_lexmark_low_offset_calibration: offset=(0x%02x,0x%02x,0x%02x).\n",
 | 
						|
       dev->offset.red, dev->offset.green, dev->offset.blue);
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_offset_calibration: end.\n");
 | 
						|
  free (data);
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * we scan a white area until average is good enough
 | 
						|
 * level is good enough when it maximize the range value of output:
 | 
						|
 * ie max-min is maximum
 | 
						|
 */
 | 
						|
SANE_Status
 | 
						|
sanei_lexmark_low_gain_calibration (Lexmark_Device * dev)
 | 
						|
{
 | 
						|
  SANE_Byte regs[255];		/* we have our own copy of shadow registers */
 | 
						|
  SANE_Status status = SANE_STATUS_GOOD;
 | 
						|
  int i, lines = 4, yoffset = 1;
 | 
						|
  int sx, ex;
 | 
						|
  int pixels;
 | 
						|
  /* averages */
 | 
						|
  int ra, ga, ba, average;
 | 
						|
  SANE_Byte *data = NULL;
 | 
						|
  int red, green, blue;
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
  char title[20];
 | 
						|
#endif
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_gain_calibration: start\n");
 | 
						|
  /* copy registers */
 | 
						|
  for (i = 0; i < 255; i++)
 | 
						|
    regs[i] = dev->shadow_regs[i];
 | 
						|
 | 
						|
  /* we clear movement bit */
 | 
						|
  regs[0xc3] = regs[0xc3] & 0x7f;
 | 
						|
  sx = regs[0x67] * 256 + regs[0x66];
 | 
						|
  ex = regs[0x6d] * 256 + regs[0x6c];
 | 
						|
  pixels = (ex - sx) / regs[0x7a];
 | 
						|
 | 
						|
  /* set up inital gains */
 | 
						|
  red = 6;
 | 
						|
  green = 6;
 | 
						|
  blue = 6;
 | 
						|
  rts88xx_set_gain (regs, red, green, blue);
 | 
						|
 | 
						|
  /* init loop */
 | 
						|
  i = 0;
 | 
						|
  ra = 0;
 | 
						|
  ba = 0;
 | 
						|
  ga = 0;
 | 
						|
 | 
						|
  status = low_cancel (dev->devnum);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    return status;
 | 
						|
 | 
						|
  /* we do a simple scan all 3 averages give the choosen level */
 | 
						|
  while (((rts88xx_is_color (regs)
 | 
						|
	   && ((ra < dev->sensor->red_gain_target)
 | 
						|
	       || (ga < dev->sensor->green_gain_target)
 | 
						|
	       || (ba < dev->sensor->blue_gain_target)))
 | 
						|
	  || (!rts88xx_is_color (regs)
 | 
						|
	      && (ga < dev->sensor->gray_gain_target))) && (i < 25))
 | 
						|
    {
 | 
						|
      status =
 | 
						|
	low_simple_scan (dev, regs, sx, pixels, yoffset, lines, &data);
 | 
						|
      if (status != SANE_STATUS_GOOD)
 | 
						|
	{
 | 
						|
	  DBG (1,
 | 
						|
	       "sanei_lexmark_low_gain_calibration: low_simple_scan failed!\n");
 | 
						|
	  if (data != NULL)
 | 
						|
	    free (data);
 | 
						|
	  return status;
 | 
						|
	}
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
      sprintf (title, "gain%02d.pnm", i);
 | 
						|
      write_pnm_file(title,pixels,lines,rts88xx_is_color (regs),data);
 | 
						|
#endif
 | 
						|
      average = average_area (regs, data, pixels, lines, &ra, &ga, &ba);
 | 
						|
      free (data);
 | 
						|
      if (ra < dev->sensor->red_gain_target)
 | 
						|
	red++;
 | 
						|
      if (ga < dev->sensor->green_gain_target
 | 
						|
	  || (dev->sensor->gray_gain_target && !rts88xx_is_color (regs)))
 | 
						|
	green++;
 | 
						|
      if (ba < dev->sensor->blue_gain_target)
 | 
						|
	blue++;
 | 
						|
      rts88xx_set_gain (regs, red, green, blue);
 | 
						|
      i++;
 | 
						|
    }
 | 
						|
  dev->gain.red = red;
 | 
						|
  dev->gain.green = green;
 | 
						|
  dev->gain.blue = blue;
 | 
						|
  dev->gain.gray = green;
 | 
						|
  DBG (7,
 | 
						|
       "sanei_lexmark_low_gain_calibration: gain=(0x%02x,0x%02x,0x%02x).\n",
 | 
						|
       dev->gain.red, dev->gain.green, dev->gain.blue);
 | 
						|
  DBG (2, "sanei_lexmark_low_gain_calibration: end.\n");
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * there is no hardware shading correction. So we have to do it in software.
 | 
						|
 * We do it by scanning a pure white area which is before scanning area. Then
 | 
						|
 * we compute per pixel coefficient to move the scanned value to the target
 | 
						|
 * value. These coefficients are used later to correct scanned data.
 | 
						|
 * The scan is done with all the final scan settings but the heigth and vertical
 | 
						|
 * start position.
 | 
						|
 */
 | 
						|
SANE_Status
 | 
						|
sanei_lexmark_low_shading_calibration (Lexmark_Device * dev)
 | 
						|
{
 | 
						|
  SANE_Byte regs[255];		/* we have our own copy of shadow registers */
 | 
						|
  int i, j, pixels, bpl;
 | 
						|
  int sx, ex;
 | 
						|
  SANE_Byte *data = NULL;
 | 
						|
  SANE_Status status;
 | 
						|
  /* enough 75 dpi lines to "go off" home position dot,
 | 
						|
     and include shading area */
 | 
						|
  int lines = 4 + 4;
 | 
						|
  int yoffset = 1;
 | 
						|
  int x, y;
 | 
						|
  float rtarget, btarget, gtarget;
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_shading_calibration: start\n");
 | 
						|
  /* copy registers */
 | 
						|
  for (i = 0; i < 255; i++)
 | 
						|
    regs[i] = dev->shadow_regs[i];
 | 
						|
 | 
						|
  /* allocate memory for scan */
 | 
						|
  sx = regs[0x67] * 256 + regs[0x66];
 | 
						|
  ex = regs[0x6d] * 256 + regs[0x6c];
 | 
						|
  DBG (7, "startx=%d, endx=%d, coef=%d, r2f=0x%02x\n",
 | 
						|
       sx, ex, regs[0x7a], regs[0x2f]);
 | 
						|
  pixels = (ex - sx) / regs[0x7a];
 | 
						|
  if (rts88xx_is_color (regs))
 | 
						|
    bpl = 3 * pixels;
 | 
						|
  else
 | 
						|
    bpl = pixels;
 | 
						|
 | 
						|
  /* adjust the target area to the scanning resolution */
 | 
						|
  lines = (8 * lines) / regs[0x7a];
 | 
						|
 | 
						|
  data = (SANE_Byte *) malloc (bpl * lines);
 | 
						|
  DBG (7, "pixels=%d, lines=%d, size=%d\n", pixels, lines, bpl * lines);
 | 
						|
  if (data == NULL)
 | 
						|
    {
 | 
						|
      DBG (2,
 | 
						|
	   "sanei_lexmark_low_shading_calibration: failed to allocate %d bytes !\n",
 | 
						|
	   bpl * lines);
 | 
						|
      return SANE_STATUS_NO_MEM;
 | 
						|
    }
 | 
						|
  if (dev->shading_coeff != NULL)
 | 
						|
    free (dev->shading_coeff);
 | 
						|
  dev->shading_coeff = (float *) malloc (bpl * sizeof (float));
 | 
						|
  if (dev->shading_coeff == NULL)
 | 
						|
    {
 | 
						|
      DBG (2,
 | 
						|
	   "sanei_lexmark_low_shading_calibration: failed to allocate %d floats !\n",
 | 
						|
	   bpl);
 | 
						|
      free (data);
 | 
						|
      return SANE_STATUS_NO_MEM;
 | 
						|
    }
 | 
						|
 | 
						|
  /* we set movement bit this time */
 | 
						|
  regs[0xc3] = regs[0xc3] | 0x80;
 | 
						|
 | 
						|
  /* execute scan */
 | 
						|
  status = low_simple_scan (dev, regs, sx, pixels, yoffset, lines, &data);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    {
 | 
						|
      DBG (1,
 | 
						|
	   "sanei_lexmark_low_shading_calibration: low_simple_scan failed!\n");
 | 
						|
      if (data != NULL)
 | 
						|
	free (data);
 | 
						|
      return status;
 | 
						|
    }
 | 
						|
 | 
						|
  yoffset = -1;
 | 
						|
  /* the very first lines of the scan may include the dark dot used
 | 
						|
   * locate park position. We find the first line free of it in the scan.
 | 
						|
   * We can't use is_home_line since it modifies data.
 | 
						|
   */
 | 
						|
  for (y = 0; (y < lines) && (yoffset == y - 1); y++)
 | 
						|
    {
 | 
						|
      if (rts88xx_is_color (regs))
 | 
						|
	{
 | 
						|
	  for (x = 0; x < 3 * pixels; x++)
 | 
						|
	    {
 | 
						|
	      if (data[x + y * 3 * pixels] < 30)
 | 
						|
		yoffset = y;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  for (x = 0; x < pixels; x++)
 | 
						|
	    {
 | 
						|
	      if (data[x + y * pixels] < 30)
 | 
						|
		yoffset = y;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
  /* make sure we are really out of the dot */
 | 
						|
  yoffset++;
 | 
						|
 | 
						|
  /* yoffset is index of last dot line, go to first white line */
 | 
						|
  if (yoffset >= lines - 1)
 | 
						|
    {
 | 
						|
      DBG (7,
 | 
						|
	   "sanei_lexmark_low_shading_calibration: failed to detect yoffset.\n");
 | 
						|
      /* fail safe fallback, picture will be altered at dot position,
 | 
						|
         but scanner is safe */
 | 
						|
      yoffset = lines - 2;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    yoffset++;
 | 
						|
  DBG (7, "sanei_lexmark_low_shading_calibration: yoffset=%d.\n", yoffset);
 | 
						|
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
  write_pnm_file("shading.pnm",pixels,lines,rts88xx_is_color (regs),data);
 | 
						|
#endif
 | 
						|
 | 
						|
  /* computes coefficients */
 | 
						|
  /* there are 8 lines usable for shading calibration at 150 dpi, between
 | 
						|
     bottom of "home position" dot and the start of the scanner's window 
 | 
						|
     assembly, we only use 7 of them */
 | 
						|
  if (yoffset + (8 * 4) / regs[0x7a] < lines)
 | 
						|
    lines = yoffset + (8 * 4) / regs[0x7a];
 | 
						|
  rtarget = dev->sensor->red_shading_target;
 | 
						|
  gtarget = dev->sensor->green_shading_target;
 | 
						|
  btarget = dev->sensor->blue_shading_target;
 | 
						|
  for (i = 0; i < pixels; i++)
 | 
						|
    {
 | 
						|
      /* we computes the coefficient needed to move the scanned value to
 | 
						|
         the target value */
 | 
						|
      if (rts88xx_is_color (dev->shadow_regs))
 | 
						|
	{
 | 
						|
	  /* RED */
 | 
						|
	  dev->shading_coeff[i] = 0;
 | 
						|
	  for (j = yoffset; j < lines; j++)
 | 
						|
	    dev->shading_coeff[i] += data[i + j * bpl];
 | 
						|
	  dev->shading_coeff[i] =
 | 
						|
	    (rtarget / (dev->shading_coeff[i] / (lines - yoffset)));
 | 
						|
 | 
						|
	  /* GREEN */
 | 
						|
	  dev->shading_coeff[i + pixels] = 0;
 | 
						|
	  for (j = yoffset; j < lines; j++)
 | 
						|
	    dev->shading_coeff[i + pixels] += data[i + j * bpl + pixels];
 | 
						|
	  dev->shading_coeff[i + pixels] =
 | 
						|
	    ((gtarget / dev->shading_coeff[i + pixels]) * (lines - yoffset));
 | 
						|
 | 
						|
	  /* BLUE */
 | 
						|
	  dev->shading_coeff[i + 2 * pixels] = 0;
 | 
						|
	  for (j = yoffset; j < lines; j++)
 | 
						|
	    dev->shading_coeff[i + 2 * pixels] +=
 | 
						|
	      data[i + j * bpl + 2 * pixels];
 | 
						|
	  dev->shading_coeff[i + 2 * pixels] =
 | 
						|
	    ((btarget / dev->shading_coeff[i + 2 * pixels]) *
 | 
						|
	     (lines - yoffset));
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  dev->shading_coeff[i] = 0;
 | 
						|
	  for (j = yoffset; j < lines; j++)
 | 
						|
	    {
 | 
						|
	      dev->shading_coeff[i] += data[i + j * bpl];
 | 
						|
	    }
 | 
						|
	  dev->shading_coeff[i] =
 | 
						|
	    (rtarget / dev->shading_coeff[i]) * (lines - yoffset);
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  /* do the scan backward to go back to start position */
 | 
						|
  regs[0xc6] &= 0xF7;
 | 
						|
  lines = (8 * 8) / regs[0x7a];
 | 
						|
 | 
						|
  /* execute scan */
 | 
						|
  status = low_simple_scan (dev, regs, sx, pixels, 1, lines, &data);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    {
 | 
						|
      DBG (1,
 | 
						|
	   "sanei_lexmark_low_shading_calibration: low_simple_scan failed!\n");
 | 
						|
      return status;
 | 
						|
    }
 | 
						|
 | 
						|
#ifdef DEEP_DEBUG
 | 
						|
  write_pnm_file("shading_bwd.pnm",pixels,lines,rts88xx_is_color (regs),data);
 | 
						|
#endif
 | 
						|
  free (data);
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_shading_calibration: end.\n");
 | 
						|
  return status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
SANE_Status
 | 
						|
sanei_lexmark_low_calibration (Lexmark_Device * dev)
 | 
						|
{
 | 
						|
  SANE_Status status;
 | 
						|
 | 
						|
  status = sanei_lexmark_low_offset_calibration (dev);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    return status;
 | 
						|
 | 
						|
  /* we put the offset just computed in scanning regs */
 | 
						|
  if (rts88xx_is_color (dev->shadow_regs))
 | 
						|
    {
 | 
						|
      rts88xx_set_offset (dev->shadow_regs,
 | 
						|
			  dev->offset.red,
 | 
						|
			  dev->offset.green, dev->offset.blue);
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      rts88xx_set_offset (dev->shadow_regs,
 | 
						|
			  dev->offset.gray,
 | 
						|
			  dev->offset.gray, dev->offset.gray);
 | 
						|
    }
 | 
						|
 | 
						|
  /* if manual gain settings, no gain calibration */
 | 
						|
  if (dev->val[OPT_MANUAL_GAIN].w == SANE_TRUE)
 | 
						|
    {
 | 
						|
      if (rts88xx_is_color (dev->shadow_regs))
 | 
						|
	{
 | 
						|
	  dev->gain.red = dev->val[OPT_RED_GAIN].w;
 | 
						|
	  dev->gain.green = dev->val[OPT_GREEN_GAIN].w;
 | 
						|
	  dev->gain.blue = dev->val[OPT_BLUE_GAIN].w;
 | 
						|
	}
 | 
						|
      else
 | 
						|
	dev->gain.gray = dev->val[OPT_GRAY_GAIN].w;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      status = sanei_lexmark_low_gain_calibration (dev);
 | 
						|
      if (status != SANE_STATUS_GOOD)
 | 
						|
	return status;
 | 
						|
    }
 | 
						|
 | 
						|
  /* put the calibrated or manual settings before shading calibration 
 | 
						|
     which must be done with final setting values */
 | 
						|
  if (rts88xx_is_color (dev->shadow_regs))
 | 
						|
    {
 | 
						|
      rts88xx_set_gain (dev->shadow_regs, dev->gain.red, dev->gain.green,
 | 
						|
			dev->gain.blue);
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      rts88xx_set_gain (dev->shadow_regs, dev->gain.gray, dev->gain.gray,
 | 
						|
			dev->gain.gray);
 | 
						|
    }
 | 
						|
 | 
						|
  status = sanei_lexmark_low_shading_calibration (dev);
 | 
						|
  if (status != SANE_STATUS_GOOD)
 | 
						|
    return status;
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_calibration: end.\n");
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
/* assign sensor data */
 | 
						|
static SANE_Status
 | 
						|
sanei_lexmark_low_assign_sensor (Lexmark_Device * dev)
 | 
						|
{
 | 
						|
  int dn;
 | 
						|
 | 
						|
  /* init sensor data */
 | 
						|
  dn = 0;
 | 
						|
  while (sensor_list[dn].id != 0
 | 
						|
	 && sensor_list[dn].id != dev->model.sensor_type)
 | 
						|
    dn++;
 | 
						|
  if (sensor_list[dn].id == 0)
 | 
						|
    {
 | 
						|
      DBG (1,
 | 
						|
	   "sanei_lexmark_low_assign_sensor: unknown sensor %d\n",
 | 
						|
	   dev->model.sensor_type);
 | 
						|
      return SANE_STATUS_UNSUPPORTED;
 | 
						|
    }
 | 
						|
  dev->sensor = &(sensor_list[dn]);
 | 
						|
  DBG (1, "sanei_lexmark_low_assign_sensor: assigned sensor number %d\n",
 | 
						|
       dev->model.sensor_type);
 | 
						|
  return SANE_STATUS_GOOD;
 | 
						|
}
 | 
						|
 | 
						|
/* assign model description, based on USB id, and register B0 when
 | 
						|
 * available */
 | 
						|
SANE_Status
 | 
						|
sanei_lexmark_low_assign_model (Lexmark_Device * dev, char *devname,
 | 
						|
				  SANE_Int vendor, SANE_Int product,
 | 
						|
				  SANE_Byte mainboard)
 | 
						|
{
 | 
						|
  int dn;
 | 
						|
  SANE_Bool found = SANE_FALSE;
 | 
						|
 | 
						|
  DBG (2, "sanei_lexmark_low_assign_model: start\n");
 | 
						|
  DBG (3,
 | 
						|
       "sanei_lexmark_low_assign_model: assigning %04x:%04x, variant %d\n",
 | 
						|
       vendor, product, mainboard);
 | 
						|
 | 
						|
  dn = 0;
 | 
						|
  /* walk the list of known devices */
 | 
						|
  while (!found && model_list[dn].vendor_id != 0)
 | 
						|
    {
 | 
						|
      /* no mainboard id given (at attach time) */
 | 
						|
      if (mainboard == 0
 | 
						|
	  && vendor == model_list[dn].vendor_id
 | 
						|
	  && product == model_list[dn].product_id)
 | 
						|
	found = SANE_TRUE;
 | 
						|
      /* mainboard given (init time) */
 | 
						|
      if (mainboard != 0
 | 
						|
	  && mainboard == model_list[dn].mainboard_id
 | 
						|
	  && vendor == model_list[dn].vendor_id
 | 
						|
	  && product == model_list[dn].product_id)
 | 
						|
	found = SANE_TRUE;
 | 
						|
 | 
						|
      if (!found)
 | 
						|
	dn++;
 | 
						|
    }
 | 
						|
 | 
						|
  /* we hit the end of list, so we don't know about the current model */
 | 
						|
  if (!found)
 | 
						|
    {
 | 
						|
      DBG (1,
 | 
						|
	   "sanei_lexmark_low_assign_model: unknown device 0x%04x:0x%04x\n",
 | 
						|
	   vendor, product);
 | 
						|
      return SANE_STATUS_UNSUPPORTED;
 | 
						|
    }
 | 
						|
 | 
						|
  dev->sane.name = strdup (devname);
 | 
						|
  dev->sane.vendor = model_list[dn].vendor;
 | 
						|
  dev->sane.model = model_list[dn].model;
 | 
						|
  dev->model = model_list[dn];
 | 
						|
  dev->sane.type = "flatbed scanner";
 | 
						|
 | 
						|
  DBG (3, "sanei_lexmark_low_assign_model: assigned %s\n",
 | 
						|
       dev->model.model);
 | 
						|
 | 
						|
  /* init sensor data */
 | 
						|
  return sanei_lexmark_low_assign_sensor (dev);
 | 
						|
  DBG (2, "sanei_lexmark_low_assign_model: end.\n");
 | 
						|
}
 |