kopia lustrzana https://gitlab.com/sane-project/backends
				
				
				
			
		
			
				
	
	
		
			1581 wiersze
		
	
	
		
			45 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			1581 wiersze
		
	
	
		
			45 KiB
		
	
	
	
		
			C
		
	
	
/*
 | 
						|
   Copyright (C) 2008, Panasonic Russia Ltd.
 | 
						|
*/
 | 
						|
/* sane - Scanner Access Now Easy.
 | 
						|
   Panasonic KV-S1020C / KV-S1025C USB scanners.
 | 
						|
*/
 | 
						|
 | 
						|
#define DEBUG_DECLARE_ONLY
 | 
						|
 | 
						|
#include "../include/sane/config.h"
 | 
						|
 | 
						|
#include <errno.h>
 | 
						|
#include <fcntl.h>
 | 
						|
#include <limits.h>
 | 
						|
#include <signal.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <sys/types.h>
 | 
						|
#include <sys/wait.h>
 | 
						|
#include <unistd.h>
 | 
						|
 | 
						|
#include "../include/sane/sane.h"
 | 
						|
#include "../include/sane/saneopts.h"
 | 
						|
#include "../include/sane/sanei.h"
 | 
						|
#include "../include/sane/sanei_usb.h"
 | 
						|
#include "../include/sane/sanei_backend.h"
 | 
						|
#include "../include/sane/sanei_config.h"
 | 
						|
#include "../include/lassert.h"
 | 
						|
 | 
						|
#include "kvs1025.h"
 | 
						|
#include "kvs1025_low.h"
 | 
						|
 | 
						|
#include "../include/sane/sanei_debug.h"
 | 
						|
 | 
						|
/* Option lists */
 | 
						|
 | 
						|
static SANE_String_Const go_scan_mode_list[] = {
 | 
						|
  SANE_I18N ("bw"),
 | 
						|
  SANE_I18N ("halftone"),
 | 
						|
  SANE_I18N ("gray"),
 | 
						|
  SANE_I18N ("color"),
 | 
						|
  NULL
 | 
						|
};
 | 
						|
 | 
						|
/*
 | 
						|
static int go_scan_mode_val[] = {
 | 
						|
    0x00,
 | 
						|
    0x01,
 | 
						|
    0x02,
 | 
						|
    0x05
 | 
						|
};*/
 | 
						|
 | 
						|
static const SANE_Word go_resolutions_list[] = {
 | 
						|
  11,				/* list size */
 | 
						|
  100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600
 | 
						|
};
 | 
						|
 | 
						|
/* List of scan sources */
 | 
						|
static SANE_String_Const go_scan_source_list[] = {
 | 
						|
  SANE_I18N ("adf"),
 | 
						|
  SANE_I18N ("fb"),
 | 
						|
  NULL
 | 
						|
};
 | 
						|
static const int go_scan_source_val[] = {
 | 
						|
  0,
 | 
						|
  0x1
 | 
						|
};
 | 
						|
 | 
						|
/* List of feeder modes */
 | 
						|
static SANE_String_Const go_feeder_mode_list[] = {
 | 
						|
  SANE_I18N ("single"),
 | 
						|
  SANE_I18N ("continuous"),
 | 
						|
  NULL
 | 
						|
};
 | 
						|
static const int go_feeder_mode_val[] = {
 | 
						|
  0x00,
 | 
						|
  0xff
 | 
						|
};
 | 
						|
 | 
						|
/* List of manual feed mode */
 | 
						|
static SANE_String_Const go_manual_feed_list[] = {
 | 
						|
  SANE_I18N ("off"),
 | 
						|
  SANE_I18N ("wait_doc"),
 | 
						|
  SANE_I18N ("wait_key"),
 | 
						|
  NULL
 | 
						|
};
 | 
						|
static const int go_manual_feed_val[] = {
 | 
						|
  0x00,
 | 
						|
  0x01,
 | 
						|
  0x02
 | 
						|
};
 | 
						|
 | 
						|
/* List of paper sizes */
 | 
						|
static SANE_String_Const go_paper_list[] = {
 | 
						|
  SANE_I18N ("user_def"),
 | 
						|
  SANE_I18N ("business_card"),
 | 
						|
  SANE_I18N ("Check"),
 | 
						|
  /*SANE_I18N ("A3"), */
 | 
						|
  SANE_I18N ("A4"),
 | 
						|
  SANE_I18N ("A5"),
 | 
						|
  SANE_I18N ("A6"),
 | 
						|
  SANE_I18N ("Letter"),
 | 
						|
  /*SANE_I18N ("Double letter 11x17 in"),
 | 
						|
     SANE_I18N ("B4"), */
 | 
						|
  SANE_I18N ("B5"),
 | 
						|
  SANE_I18N ("B6"),
 | 
						|
  SANE_I18N ("Legal"),
 | 
						|
  NULL
 | 
						|
};
 | 
						|
static const int go_paper_val[] = {
 | 
						|
  0x00,
 | 
						|
  0x01,
 | 
						|
  0x02,
 | 
						|
  /*0x03, *//* A3 : not supported */
 | 
						|
  0x04,
 | 
						|
  0x05,
 | 
						|
  0x06,
 | 
						|
  0x07,
 | 
						|
  /*0x09,
 | 
						|
     0x0C, *//* Dbl letter and B4 : not supported */
 | 
						|
  0x0D,
 | 
						|
  0x0E,
 | 
						|
  0x0F
 | 
						|
};
 | 
						|
 | 
						|
static const KV_PAPER_SIZE go_paper_sizes[] = {
 | 
						|
  {210, 297},			/* User defined, default=A4 */
 | 
						|
  {54, 90},			/* Business card */
 | 
						|
  {80, 170},			/* Check (China business) */
 | 
						|
  /*{297, 420}, *//* A3 */
 | 
						|
  {210, 297},			/* A4 */
 | 
						|
  {148, 210},			/* A5 */
 | 
						|
  {105, 148},			/* A6 */
 | 
						|
  {216, 280},			/* US Letter 8.5 x 11 in */
 | 
						|
  /*{280, 432}, *//* Double Letter 11 x 17 in */
 | 
						|
  /*{250, 353}, *//* B4 */
 | 
						|
  {176, 250},			/* B5 */
 | 
						|
  {125, 176},			/* B6 */
 | 
						|
  {216, 356}			/* US Legal */
 | 
						|
};
 | 
						|
 | 
						|
static const int default_paper_size_idx = 3;	/* A4 */
 | 
						|
 | 
						|
/* Lists of supported halftone. They are only valid with
 | 
						|
 * for the Black&White mode. */
 | 
						|
static SANE_String_Const go_halftone_pattern_list[] = {
 | 
						|
  SANE_I18N ("bayer_64"),
 | 
						|
  SANE_I18N ("bayer_16"),
 | 
						|
  SANE_I18N ("halftone_32"),
 | 
						|
  SANE_I18N ("halftone_64"),
 | 
						|
  SANE_I18N ("diffusion"),
 | 
						|
  NULL
 | 
						|
};
 | 
						|
static const int go_halftone_pattern_val[] = {
 | 
						|
  0x00,
 | 
						|
  0x01,
 | 
						|
  0x02,
 | 
						|
  0x03,
 | 
						|
  0x04
 | 
						|
};
 | 
						|
 | 
						|
/* List of automatic threshold options */
 | 
						|
static SANE_String_Const go_automatic_threshold_list[] = {
 | 
						|
  SANE_I18N ("normal"),
 | 
						|
  SANE_I18N ("light"),
 | 
						|
  SANE_I18N ("dark"),
 | 
						|
  NULL
 | 
						|
};
 | 
						|
static const int go_automatic_threshold_val[] = {
 | 
						|
  0,
 | 
						|
  0x11,
 | 
						|
  0x1f
 | 
						|
};
 | 
						|
 | 
						|
/* List of white level base. */
 | 
						|
static SANE_String_Const go_white_level_list[] = {
 | 
						|
  SANE_I18N ("From scanner"),
 | 
						|
  SANE_I18N ("From paper"),
 | 
						|
  SANE_I18N ("Automatic"),
 | 
						|
  NULL
 | 
						|
};
 | 
						|
static const int go_white_level_val[] = {
 | 
						|
  0x00,
 | 
						|
  0x80,
 | 
						|
  0x81
 | 
						|
};
 | 
						|
 | 
						|
/* List of noise reduction options. */
 | 
						|
static SANE_String_Const go_noise_reduction_list[] = {
 | 
						|
  SANE_I18N ("default"),
 | 
						|
  "1x1",
 | 
						|
  "2x2",
 | 
						|
  "3x3",
 | 
						|
  "4x4",
 | 
						|
  "5x5",
 | 
						|
  NULL
 | 
						|
};
 | 
						|
static const int go_noise_reduction_val[] = {
 | 
						|
  0x00,
 | 
						|
  0x01,
 | 
						|
  0x02,
 | 
						|
  0x03,
 | 
						|
  0x04,
 | 
						|
  0x05
 | 
						|
};
 | 
						|
 | 
						|
/* List of image emphasis options, 5 steps */
 | 
						|
static SANE_String_Const go_image_emphasis_list[] = {
 | 
						|
  SANE_I18N ("smooth"),
 | 
						|
  SANE_I18N ("none"),
 | 
						|
  SANE_I18N ("low"),
 | 
						|
  SANE_I18N ("medium"),		/* default */
 | 
						|
  SANE_I18N ("high"),
 | 
						|
  NULL
 | 
						|
};
 | 
						|
static const int go_image_emphasis_val[] = {
 | 
						|
  0x14,
 | 
						|
  0x00,
 | 
						|
  0x11,
 | 
						|
  0x12,
 | 
						|
  0x13
 | 
						|
};
 | 
						|
 | 
						|
/* List of gamma */
 | 
						|
static SANE_String_Const go_gamma_list[] = {
 | 
						|
  SANE_I18N ("normal"),
 | 
						|
  SANE_I18N ("crt"),
 | 
						|
  SANE_I18N ("linear"),
 | 
						|
  NULL
 | 
						|
};
 | 
						|
static const int go_gamma_val[] = {
 | 
						|
  0x00,
 | 
						|
  0x01,
 | 
						|
  0x02
 | 
						|
};
 | 
						|
 | 
						|
/* List of lamp color dropout */
 | 
						|
static SANE_String_Const go_lamp_list[] = {
 | 
						|
  SANE_I18N ("normal"),
 | 
						|
  SANE_I18N ("red"),
 | 
						|
  SANE_I18N ("green"),
 | 
						|
  SANE_I18N ("blue"),
 | 
						|
  NULL
 | 
						|
};
 | 
						|
static const int go_lamp_val[] = {
 | 
						|
  0x00,
 | 
						|
  0x01,
 | 
						|
  0x02,
 | 
						|
  0x03
 | 
						|
};
 | 
						|
 | 
						|
static SANE_Range go_value_range = { 0, 255, 0 };
 | 
						|
 | 
						|
static SANE_Range go_jpeg_compression_range = { 0, 0x64, 0 };
 | 
						|
 | 
						|
static SANE_Range go_rotate_range = { 0, 270, 90 };
 | 
						|
 | 
						|
static SANE_Range go_swdespeck_range = { 0, 9, 1 };
 | 
						|
 | 
						|
static SANE_Range go_swskip_range = { SANE_FIX(0), SANE_FIX(100), 1 };
 | 
						|
 | 
						|
static const char *go_option_name[] = {
 | 
						|
  "OPT_NUM_OPTS",
 | 
						|
 | 
						|
  /* General options */
 | 
						|
  "OPT_MODE_GROUP",
 | 
						|
  "OPT_MODE",			/* scanner modes */
 | 
						|
  "OPT_RESOLUTION",		/* X and Y resolution */
 | 
						|
  "OPT_DUPLEX",			/* Duplex mode */
 | 
						|
  "OPT_SCAN_SOURCE",		/* Scan source, fixed to ADF */
 | 
						|
  "OPT_FEEDER_MODE",		/* Feeder mode, fixed to Continuous */
 | 
						|
  "OPT_LONGPAPER",		/* Long paper mode */
 | 
						|
  "OPT_LENGTHCTL",		/* Length control mode */
 | 
						|
  "OPT_MANUALFEED",		/* Manual feed mode */
 | 
						|
  "OPT_FEED_TIMEOUT",		/* Feed timeout */
 | 
						|
  "OPT_DBLFEED",		/* Double feed detection mode */
 | 
						|
  "OPT_FIT_TO_PAGE",		/* Scanner shrinks image to fit scanned page */
 | 
						|
 | 
						|
  /* Geometry group */
 | 
						|
  "OPT_GEOMETRY_GROUP",
 | 
						|
  "OPT_PAPER_SIZE",		/* Paper size */
 | 
						|
  "OPT_LANDSCAPE",		/* true if landscape */
 | 
						|
  "OPT_TL_X",			/* upper left X */
 | 
						|
  "OPT_TL_Y",			/* upper left Y */
 | 
						|
  "OPT_BR_X",			/* bottom right X */
 | 
						|
  "OPT_BR_Y",			/* bottom right Y */
 | 
						|
 | 
						|
  "OPT_ENHANCEMENT_GROUP",
 | 
						|
  "OPT_BRIGHTNESS",		/* Brightness */
 | 
						|
  "OPT_CONTRAST",		/* Contrast */
 | 
						|
  "OPT_AUTOMATIC_THRESHOLD",	/* Binary threshold */
 | 
						|
  "OPT_HALFTONE_PATTERN",	/* Halftone pattern */
 | 
						|
  "OPT_AUTOMATIC_SEPARATION",	/* Automatic separation */
 | 
						|
  "OPT_WHITE_LEVEL",		/* White level */
 | 
						|
  "OPT_NOISE_REDUCTION",	/* Noise reduction */
 | 
						|
  "OPT_IMAGE_EMPHASIS",		/* Image emphasis */
 | 
						|
  "OPT_GAMMA",			/* Gamma */
 | 
						|
  "OPT_LAMP",			/* Lamp -- color drop out */
 | 
						|
  "OPT_INVERSE",		/* Inverse image */
 | 
						|
  "OPT_MIRROR",			/* Mirror image */
 | 
						|
  "OPT_JPEG",			/* JPEG Compression */
 | 
						|
  "OPT_ROTATE",         	/* Rotate image */
 | 
						|
 | 
						|
  "OPT_SWDESKEW",               /* Software deskew */
 | 
						|
  "OPT_SWDESPECK",              /* Software despeckle */
 | 
						|
  "OPT_SWDEROTATE",             /* Software detect/correct 90 deg. rotation */
 | 
						|
  "OPT_SWCROP",                 /* Software autocrop */
 | 
						|
  "OPT_SWSKIP",                 /* Software blank page skip */
 | 
						|
 | 
						|
  /* must come last: */
 | 
						|
  "OPT_NUM_OPTIONS"
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/* Round to boundry, return 1 if value modified */
 | 
						|
static int
 | 
						|
round_to_boundry (SANE_Word * pval, SANE_Word boundry,
 | 
						|
		  SANE_Word minv, SANE_Word maxv)
 | 
						|
{
 | 
						|
  SANE_Word lower, upper, k, v;
 | 
						|
 | 
						|
  v = *pval;
 | 
						|
  k = v / boundry;
 | 
						|
  lower = k * boundry;
 | 
						|
  upper = (k + 1) * boundry;
 | 
						|
 | 
						|
  if (v - lower <= upper - v)
 | 
						|
    {
 | 
						|
      *pval = lower;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      *pval = upper;
 | 
						|
    }
 | 
						|
 | 
						|
  if ((*pval) < minv)
 | 
						|
    *pval = minv;
 | 
						|
  if ((*pval) > maxv)
 | 
						|
    *pval = maxv;
 | 
						|
 | 
						|
  return ((*pval) != v);
 | 
						|
}
 | 
						|
 | 
						|
/* Returns the length of the longest string, including the terminating
 | 
						|
 * character. */
 | 
						|
static size_t
 | 
						|
max_string_size (SANE_String_Const * strings)
 | 
						|
{
 | 
						|
  size_t size, max_size = 0;
 | 
						|
  int i;
 | 
						|
 | 
						|
  for (i = 0; strings[i]; ++i)
 | 
						|
    {
 | 
						|
      size = strlen (strings[i]) + 1;
 | 
						|
      if (size > max_size)
 | 
						|
	{
 | 
						|
	  max_size = size;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  return max_size;
 | 
						|
}
 | 
						|
 | 
						|
/* Lookup a string list from one array and return its index. */
 | 
						|
static int
 | 
						|
get_string_list_index (const SANE_String_Const * list, SANE_String_Const name)
 | 
						|
{
 | 
						|
  int index;
 | 
						|
 | 
						|
  index = 0;
 | 
						|
  while (list[index] != NULL)
 | 
						|
    {
 | 
						|
      if (strcmp (list[index], name) == 0)
 | 
						|
	{
 | 
						|
	  return (index);
 | 
						|
	}
 | 
						|
      index++;
 | 
						|
    }
 | 
						|
 | 
						|
  DBG (DBG_error, "System bug: option %s not found in list\n", name);
 | 
						|
 | 
						|
  return (-1);			/* not found */
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Lookup a string list from one array and return the correnpond value. */
 | 
						|
int
 | 
						|
get_optval_list (const PKV_DEV dev, int idx,
 | 
						|
		 const SANE_String_Const * str_list, const int *val_list)
 | 
						|
{
 | 
						|
  int index;
 | 
						|
 | 
						|
  index = get_string_list_index (str_list, dev->val[idx].s);
 | 
						|
 | 
						|
  if (index < 0)
 | 
						|
    index = 0;
 | 
						|
 | 
						|
  return val_list[index];
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Get device mode from device options */
 | 
						|
KV_SCAN_MODE
 | 
						|
kv_get_mode (const PKV_DEV dev)
 | 
						|
{
 | 
						|
  int i;
 | 
						|
 | 
						|
  i = get_string_list_index (go_scan_mode_list, dev->val[OPT_MODE].s);
 | 
						|
 | 
						|
  switch (i)
 | 
						|
    {
 | 
						|
    case 0:
 | 
						|
      return SM_BINARY;
 | 
						|
    case 1:
 | 
						|
      return SM_DITHER;
 | 
						|
    case 2:
 | 
						|
      return SM_GRAYSCALE;
 | 
						|
    case 3:
 | 
						|
      return SM_COLOR;
 | 
						|
    default:
 | 
						|
      assert (0 == 1);
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
kv_calc_paper_size (const PKV_DEV dev, int *w, int *h)
 | 
						|
{
 | 
						|
  int i = get_string_list_index (go_paper_list,
 | 
						|
				 dev->val[OPT_PAPER_SIZE].s);
 | 
						|
  if (i == 0)
 | 
						|
    {				/* Non-standard document */
 | 
						|
      int x_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w));
 | 
						|
      int y_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_Y].w));
 | 
						|
      int x_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w));
 | 
						|
      int y_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_Y].w));
 | 
						|
      *w = x_br - x_tl;
 | 
						|
      *h = y_br - y_tl;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      if (dev->val[OPT_LANDSCAPE].s)
 | 
						|
	{
 | 
						|
	  *h = mmToIlu (go_paper_sizes[i].width);
 | 
						|
	  *w = mmToIlu (go_paper_sizes[i].height);
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  *w = mmToIlu (go_paper_sizes[i].width);
 | 
						|
	  *h = mmToIlu (go_paper_sizes[i].height);
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* Get bit depth from scan mode */
 | 
						|
int
 | 
						|
kv_get_depth (KV_SCAN_MODE mode)
 | 
						|
{
 | 
						|
  switch (mode)
 | 
						|
    {
 | 
						|
    case SM_BINARY:
 | 
						|
    case SM_DITHER:
 | 
						|
      return 1;
 | 
						|
    case SM_GRAYSCALE:
 | 
						|
      return 8;
 | 
						|
    case SM_COLOR:
 | 
						|
      return 24;
 | 
						|
    default:
 | 
						|
      assert (0 == 1);
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
const SANE_Option_Descriptor *
 | 
						|
kv_get_option_descriptor (PKV_DEV dev, SANE_Int option)
 | 
						|
{
 | 
						|
  DBG (DBG_proc, "sane_get_option_descriptor: enter, option %s\n",
 | 
						|
       go_option_name[option]);
 | 
						|
 | 
						|
  if ((unsigned) option >= OPT_NUM_OPTIONS)
 | 
						|
    {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
  DBG (DBG_proc, "sane_get_option_descriptor: exit\n");
 | 
						|
 | 
						|
  return dev->opt + option;
 | 
						|
}
 | 
						|
 | 
						|
/* Reset the options for that scanner. */
 | 
						|
void
 | 
						|
kv_init_options (PKV_DEV dev)
 | 
						|
{
 | 
						|
  int i;
 | 
						|
 | 
						|
  if (dev->option_set)
 | 
						|
    return;
 | 
						|
 | 
						|
  DBG (DBG_proc, "kv_init_options: enter\n");
 | 
						|
 | 
						|
  /* Pre-initialize the options. */
 | 
						|
  memset (dev->opt, 0, sizeof (dev->opt));
 | 
						|
  memset (dev->val, 0, sizeof (dev->val));
 | 
						|
 | 
						|
  for (i = 0; i < OPT_NUM_OPTIONS; ++i)
 | 
						|
    {
 | 
						|
      dev->opt[i].size = sizeof (SANE_Word);
 | 
						|
      dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 | 
						|
    }
 | 
						|
 | 
						|
  /* Number of options. */
 | 
						|
  dev->opt[OPT_NUM_OPTS].name = "";
 | 
						|
  dev->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
 | 
						|
  dev->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
 | 
						|
  dev->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
 | 
						|
  dev->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
 | 
						|
  dev->val[OPT_NUM_OPTS].w = OPT_NUM_OPTIONS;
 | 
						|
 | 
						|
  /* Mode group */
 | 
						|
  dev->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode");
 | 
						|
  dev->opt[OPT_MODE_GROUP].desc = "";	/* not valid for a group */
 | 
						|
  dev->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
 | 
						|
  dev->opt[OPT_MODE_GROUP].cap = 0;
 | 
						|
  dev->opt[OPT_MODE_GROUP].size = 0;
 | 
						|
  dev->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
 | 
						|
 | 
						|
  /* Scanner supported modes */
 | 
						|
  dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
 | 
						|
  dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
 | 
						|
  dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
 | 
						|
  dev->opt[OPT_MODE].type = SANE_TYPE_STRING;
 | 
						|
  dev->opt[OPT_MODE].size = max_string_size (go_scan_mode_list);
 | 
						|
  dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | 
						|
  dev->opt[OPT_MODE].constraint.string_list = go_scan_mode_list;
 | 
						|
  dev->val[OPT_MODE].s = strdup ("");	/* will be set later */
 | 
						|
 | 
						|
  /* X and Y resolution */
 | 
						|
  dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
 | 
						|
  dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
 | 
						|
  dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
 | 
						|
  dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
 | 
						|
  dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
 | 
						|
  dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
 | 
						|
  dev->opt[OPT_RESOLUTION].constraint.word_list = go_resolutions_list;
 | 
						|
  dev->val[OPT_RESOLUTION].w = go_resolutions_list[3];
 | 
						|
 | 
						|
  /* Duplex */
 | 
						|
  dev->opt[OPT_DUPLEX].name = SANE_NAME_DUPLEX;
 | 
						|
  dev->opt[OPT_DUPLEX].title = SANE_TITLE_DUPLEX;
 | 
						|
  dev->opt[OPT_DUPLEX].desc = SANE_DESC_DUPLEX;
 | 
						|
  dev->opt[OPT_DUPLEX].type = SANE_TYPE_BOOL;
 | 
						|
  dev->opt[OPT_DUPLEX].unit = SANE_UNIT_NONE;
 | 
						|
  dev->val[OPT_DUPLEX].w = SANE_FALSE;
 | 
						|
  if (!dev->support_info.support_duplex)
 | 
						|
    dev->opt[OPT_DUPLEX].cap |= SANE_CAP_INACTIVE;
 | 
						|
 | 
						|
  /* Scan source */
 | 
						|
  dev->opt[OPT_SCAN_SOURCE].name = SANE_NAME_SCAN_SOURCE;
 | 
						|
  dev->opt[OPT_SCAN_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
 | 
						|
  dev->opt[OPT_SCAN_SOURCE].desc = SANE_I18N ("Sets the scan source");
 | 
						|
  dev->opt[OPT_SCAN_SOURCE].type = SANE_TYPE_STRING;
 | 
						|
  dev->opt[OPT_SCAN_SOURCE].size = max_string_size (go_scan_source_list);
 | 
						|
  dev->opt[OPT_SCAN_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | 
						|
  dev->opt[OPT_SCAN_SOURCE].constraint.string_list = go_scan_source_list;
 | 
						|
  dev->val[OPT_SCAN_SOURCE].s = strdup (go_scan_source_list[0]);
 | 
						|
  dev->opt[OPT_SCAN_SOURCE].cap &= ~SANE_CAP_SOFT_SELECT;
 | 
						|
  /* for KV-S1020C / KV-S1025C, scan source is fixed to ADF */
 | 
						|
 | 
						|
  /* Feeder mode */
 | 
						|
  dev->opt[OPT_FEEDER_MODE].name = "feeder-mode";
 | 
						|
  dev->opt[OPT_FEEDER_MODE].title = SANE_I18N ("Feeder mode");
 | 
						|
  dev->opt[OPT_FEEDER_MODE].desc = SANE_I18N ("Sets the feeding mode");
 | 
						|
  dev->opt[OPT_FEEDER_MODE].type = SANE_TYPE_STRING;
 | 
						|
  dev->opt[OPT_FEEDER_MODE].size = max_string_size (go_feeder_mode_list);
 | 
						|
  dev->opt[OPT_FEEDER_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | 
						|
  dev->opt[OPT_FEEDER_MODE].constraint.string_list = go_feeder_mode_list;
 | 
						|
  dev->val[OPT_FEEDER_MODE].s = strdup (go_feeder_mode_list[1]);
 | 
						|
 | 
						|
  /* Long paper */
 | 
						|
  dev->opt[OPT_LONGPAPER].name = SANE_NAME_LONGPAPER;
 | 
						|
  dev->opt[OPT_LONGPAPER].title = SANE_TITLE_LONGPAPER;
 | 
						|
  dev->opt[OPT_LONGPAPER].desc = SANE_I18N ("Enable/Disable long paper mode");
 | 
						|
  dev->opt[OPT_LONGPAPER].type = SANE_TYPE_BOOL;
 | 
						|
  dev->opt[OPT_LONGPAPER].unit = SANE_UNIT_NONE;
 | 
						|
  dev->val[OPT_LONGPAPER].w = SANE_FALSE;
 | 
						|
 | 
						|
  /* Length control */
 | 
						|
  dev->opt[OPT_LENGTHCTL].name = SANE_NAME_LENGTHCTL;
 | 
						|
  dev->opt[OPT_LENGTHCTL].title = SANE_TITLE_LENGTHCTL;
 | 
						|
  dev->opt[OPT_LENGTHCTL].desc =
 | 
						|
    SANE_I18N ("Enable/Disable length control mode");
 | 
						|
  dev->opt[OPT_LENGTHCTL].type = SANE_TYPE_BOOL;
 | 
						|
  dev->opt[OPT_LENGTHCTL].unit = SANE_UNIT_NONE;
 | 
						|
  dev->val[OPT_LENGTHCTL].w = SANE_TRUE;
 | 
						|
 | 
						|
  /* Manual feed */
 | 
						|
  dev->opt[OPT_MANUALFEED].name = SANE_NAME_MANUALFEED;
 | 
						|
  dev->opt[OPT_MANUALFEED].title = SANE_TITLE_MANUALFEED;
 | 
						|
  dev->opt[OPT_MANUALFEED].desc = SANE_I18N ("Sets the manual feed mode");
 | 
						|
  dev->opt[OPT_MANUALFEED].type = SANE_TYPE_STRING;
 | 
						|
  dev->opt[OPT_MANUALFEED].size = max_string_size (go_manual_feed_list);
 | 
						|
  dev->opt[OPT_MANUALFEED].constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | 
						|
  dev->opt[OPT_MANUALFEED].constraint.string_list = go_manual_feed_list;
 | 
						|
  dev->val[OPT_MANUALFEED].s = strdup (go_manual_feed_list[0]);
 | 
						|
 | 
						|
  /*Manual feed timeout */
 | 
						|
  dev->opt[OPT_FEED_TIMEOUT].name = SANE_NAME_FEED_TIMEOUT;
 | 
						|
  dev->opt[OPT_FEED_TIMEOUT].title = SANE_TITLE_FEED_TIMEOUT;
 | 
						|
  dev->opt[OPT_FEED_TIMEOUT].desc =
 | 
						|
    SANE_I18N ("Sets the manual feed timeout in seconds");
 | 
						|
  dev->opt[OPT_FEED_TIMEOUT].type = SANE_TYPE_INT;
 | 
						|
  dev->opt[OPT_FEED_TIMEOUT].unit = SANE_UNIT_NONE;
 | 
						|
  dev->opt[OPT_FEED_TIMEOUT].size = sizeof (SANE_Int);
 | 
						|
  dev->opt[OPT_FEED_TIMEOUT].constraint_type = SANE_CONSTRAINT_RANGE;
 | 
						|
  dev->opt[OPT_FEED_TIMEOUT].constraint.range = &(go_value_range);
 | 
						|
  dev->opt[OPT_FEED_TIMEOUT].cap |= SANE_CAP_INACTIVE;
 | 
						|
  dev->val[OPT_FEED_TIMEOUT].w = 30;
 | 
						|
 | 
						|
  /* Double feed */
 | 
						|
  dev->opt[OPT_DBLFEED].name = SANE_NAME_DBLFEED;
 | 
						|
  dev->opt[OPT_DBLFEED].title = SANE_TITLE_DBLFEED;
 | 
						|
  dev->opt[OPT_DBLFEED].desc =
 | 
						|
    SANE_I18N ("Enable/Disable double feed detection");
 | 
						|
  dev->opt[OPT_DBLFEED].type = SANE_TYPE_BOOL;
 | 
						|
  dev->opt[OPT_DBLFEED].unit = SANE_UNIT_NONE;
 | 
						|
  dev->val[OPT_DBLFEED].w = SANE_FALSE;
 | 
						|
 | 
						|
  /* Fit to page */
 | 
						|
  dev->opt[OPT_FIT_TO_PAGE].name = SANE_I18N ("fit-to-page");
 | 
						|
  dev->opt[OPT_FIT_TO_PAGE].title = SANE_I18N ("Fit to page");
 | 
						|
  dev->opt[OPT_FIT_TO_PAGE].desc =
 | 
						|
    SANE_I18N ("Scanner shrinks image to fit scanned page");
 | 
						|
  dev->opt[OPT_FIT_TO_PAGE].type = SANE_TYPE_BOOL;
 | 
						|
  dev->opt[OPT_FIT_TO_PAGE].unit = SANE_UNIT_NONE;
 | 
						|
  dev->val[OPT_FIT_TO_PAGE].w = SANE_FALSE;
 | 
						|
 | 
						|
  /* Geometry group */
 | 
						|
  dev->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry");
 | 
						|
  dev->opt[OPT_GEOMETRY_GROUP].desc = "";	/* not valid for a group */
 | 
						|
  dev->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
 | 
						|
  dev->opt[OPT_GEOMETRY_GROUP].cap = 0;
 | 
						|
  dev->opt[OPT_GEOMETRY_GROUP].size = 0;
 | 
						|
  dev->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
 | 
						|
 | 
						|
  /* Paper sizes list */
 | 
						|
  dev->opt[OPT_PAPER_SIZE].name = SANE_NAME_PAPER_SIZE;
 | 
						|
  dev->opt[OPT_PAPER_SIZE].title = SANE_TITLE_PAPER_SIZE;
 | 
						|
  dev->opt[OPT_PAPER_SIZE].desc = SANE_DESC_PAPER_SIZE;
 | 
						|
  dev->opt[OPT_PAPER_SIZE].type = SANE_TYPE_STRING;
 | 
						|
  dev->opt[OPT_PAPER_SIZE].size = max_string_size (go_paper_list);
 | 
						|
  dev->opt[OPT_PAPER_SIZE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | 
						|
  dev->opt[OPT_PAPER_SIZE].constraint.string_list = go_paper_list;
 | 
						|
  dev->val[OPT_PAPER_SIZE].s = strdup ("");	/* will be set later */
 | 
						|
 | 
						|
  /* Landscape */
 | 
						|
  dev->opt[OPT_LANDSCAPE].name = SANE_NAME_LANDSCAPE;
 | 
						|
  dev->opt[OPT_LANDSCAPE].title = SANE_TITLE_LANDSCAPE;
 | 
						|
  dev->opt[OPT_LANDSCAPE].desc =
 | 
						|
    SANE_I18N ("Set paper position : "
 | 
						|
	       "true for landscape, false for portrait");
 | 
						|
  dev->opt[OPT_LANDSCAPE].type = SANE_TYPE_BOOL;
 | 
						|
  dev->opt[OPT_LANDSCAPE].unit = SANE_UNIT_NONE;
 | 
						|
  dev->val[OPT_LANDSCAPE].w = SANE_FALSE;
 | 
						|
 | 
						|
  /* Upper left X */
 | 
						|
  dev->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
 | 
						|
  dev->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
 | 
						|
  dev->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
 | 
						|
  dev->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
 | 
						|
  dev->opt[OPT_TL_X].unit = SANE_UNIT_MM;
 | 
						|
  dev->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
 | 
						|
  dev->opt[OPT_TL_X].constraint.range = &(dev->x_range);
 | 
						|
 | 
						|
  /* Upper left Y */
 | 
						|
  dev->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
 | 
						|
  dev->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
 | 
						|
  dev->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
 | 
						|
  dev->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
 | 
						|
  dev->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
 | 
						|
  dev->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
 | 
						|
  dev->opt[OPT_TL_Y].constraint.range = &(dev->y_range);
 | 
						|
 | 
						|
  /* Bottom-right x */
 | 
						|
  dev->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
 | 
						|
  dev->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
 | 
						|
  dev->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
 | 
						|
  dev->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
 | 
						|
  dev->opt[OPT_BR_X].unit = SANE_UNIT_MM;
 | 
						|
  dev->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
 | 
						|
  dev->opt[OPT_BR_X].constraint.range = &(dev->x_range);
 | 
						|
 | 
						|
  /* Bottom-right y */
 | 
						|
  dev->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
 | 
						|
  dev->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
 | 
						|
  dev->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
 | 
						|
  dev->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
 | 
						|
  dev->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
 | 
						|
  dev->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
 | 
						|
  dev->opt[OPT_BR_Y].constraint.range = &(dev->y_range);
 | 
						|
 | 
						|
  /* Enhancement group */
 | 
						|
  dev->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement");
 | 
						|
  dev->opt[OPT_ENHANCEMENT_GROUP].desc = "";	/* not valid for a group */
 | 
						|
  dev->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
 | 
						|
  dev->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED;
 | 
						|
  dev->opt[OPT_ENHANCEMENT_GROUP].size = 0;
 | 
						|
  dev->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
 | 
						|
 | 
						|
  /* Brightness */
 | 
						|
  dev->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
 | 
						|
  dev->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
 | 
						|
  dev->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
 | 
						|
  dev->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
 | 
						|
  dev->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
 | 
						|
  dev->opt[OPT_BRIGHTNESS].size = sizeof (SANE_Int);
 | 
						|
  dev->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
 | 
						|
  dev->opt[OPT_BRIGHTNESS].constraint.range = &(go_value_range);
 | 
						|
  dev->val[OPT_BRIGHTNESS].w = 128;
 | 
						|
 | 
						|
  /* Contrast */
 | 
						|
  dev->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
 | 
						|
  dev->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
 | 
						|
  dev->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
 | 
						|
  dev->opt[OPT_CONTRAST].type = SANE_TYPE_INT;
 | 
						|
  dev->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE;
 | 
						|
  dev->opt[OPT_CONTRAST].size = sizeof (SANE_Int);
 | 
						|
  dev->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
 | 
						|
  dev->opt[OPT_CONTRAST].constraint.range = &(go_value_range);
 | 
						|
  dev->val[OPT_CONTRAST].w = 128;
 | 
						|
 | 
						|
  /* Automatic threshold */
 | 
						|
  dev->opt[OPT_AUTOMATIC_THRESHOLD].name = "automatic-threshold";
 | 
						|
  dev->opt[OPT_AUTOMATIC_THRESHOLD].title = SANE_I18N ("Automatic threshold");
 | 
						|
  dev->opt[OPT_AUTOMATIC_THRESHOLD].desc =
 | 
						|
    SANE_I18N
 | 
						|
    ("Automatically sets brightness, contrast, white level, "
 | 
						|
     "gamma, noise reduction and image emphasis");
 | 
						|
  dev->opt[OPT_AUTOMATIC_THRESHOLD].type = SANE_TYPE_STRING;
 | 
						|
  dev->opt[OPT_AUTOMATIC_THRESHOLD].size =
 | 
						|
    max_string_size (go_automatic_threshold_list);
 | 
						|
  dev->opt[OPT_AUTOMATIC_THRESHOLD].constraint_type =
 | 
						|
    SANE_CONSTRAINT_STRING_LIST;
 | 
						|
  dev->opt[OPT_AUTOMATIC_THRESHOLD].constraint.string_list =
 | 
						|
    go_automatic_threshold_list;
 | 
						|
  dev->val[OPT_AUTOMATIC_THRESHOLD].s =
 | 
						|
    strdup (go_automatic_threshold_list[0]);
 | 
						|
 | 
						|
  /* Halftone pattern */
 | 
						|
  dev->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN;
 | 
						|
  dev->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN;
 | 
						|
  dev->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN;
 | 
						|
  dev->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING;
 | 
						|
  dev->opt[OPT_HALFTONE_PATTERN].size =
 | 
						|
    max_string_size (go_halftone_pattern_list);
 | 
						|
  dev->opt[OPT_HALFTONE_PATTERN].constraint_type =
 | 
						|
    SANE_CONSTRAINT_STRING_LIST;
 | 
						|
  dev->opt[OPT_HALFTONE_PATTERN].constraint.string_list =
 | 
						|
    go_halftone_pattern_list;
 | 
						|
  dev->val[OPT_HALFTONE_PATTERN].s = strdup (go_halftone_pattern_list[0]);
 | 
						|
 | 
						|
  /* Automatic separation */
 | 
						|
  dev->opt[OPT_AUTOMATIC_SEPARATION].name = SANE_NAME_AUTOSEP;
 | 
						|
  dev->opt[OPT_AUTOMATIC_SEPARATION].title = SANE_TITLE_AUTOSEP;
 | 
						|
  dev->opt[OPT_AUTOMATIC_SEPARATION].desc = SANE_DESC_AUTOSEP;
 | 
						|
  dev->opt[OPT_AUTOMATIC_SEPARATION].type = SANE_TYPE_BOOL;
 | 
						|
  dev->opt[OPT_AUTOMATIC_SEPARATION].unit = SANE_UNIT_NONE;
 | 
						|
  dev->val[OPT_AUTOMATIC_SEPARATION].w = SANE_FALSE;
 | 
						|
 | 
						|
  /* White level base */
 | 
						|
  dev->opt[OPT_WHITE_LEVEL].name = SANE_NAME_WHITE_LEVEL;
 | 
						|
  dev->opt[OPT_WHITE_LEVEL].title = SANE_TITLE_WHITE_LEVEL;
 | 
						|
  dev->opt[OPT_WHITE_LEVEL].desc = SANE_DESC_WHITE_LEVEL;
 | 
						|
  dev->opt[OPT_WHITE_LEVEL].type = SANE_TYPE_STRING;
 | 
						|
  dev->opt[OPT_WHITE_LEVEL].size = max_string_size (go_white_level_list);
 | 
						|
  dev->opt[OPT_WHITE_LEVEL].constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | 
						|
  dev->opt[OPT_WHITE_LEVEL].constraint.string_list = go_white_level_list;
 | 
						|
  dev->val[OPT_WHITE_LEVEL].s = strdup (go_white_level_list[0]);
 | 
						|
 | 
						|
  /* Noise reduction */
 | 
						|
  dev->opt[OPT_NOISE_REDUCTION].name = "noise-reduction";
 | 
						|
  dev->opt[OPT_NOISE_REDUCTION].title = SANE_I18N ("Noise reduction");
 | 
						|
  dev->opt[OPT_NOISE_REDUCTION].desc =
 | 
						|
    SANE_I18N ("Reduce the isolated dot noise");
 | 
						|
  dev->opt[OPT_NOISE_REDUCTION].type = SANE_TYPE_STRING;
 | 
						|
  dev->opt[OPT_NOISE_REDUCTION].size =
 | 
						|
    max_string_size (go_noise_reduction_list);
 | 
						|
  dev->opt[OPT_NOISE_REDUCTION].constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | 
						|
  dev->opt[OPT_NOISE_REDUCTION].constraint.string_list =
 | 
						|
    go_noise_reduction_list;
 | 
						|
  dev->val[OPT_NOISE_REDUCTION].s = strdup (go_noise_reduction_list[0]);
 | 
						|
 | 
						|
  /* Image emphasis */
 | 
						|
  dev->opt[OPT_IMAGE_EMPHASIS].name = "image-emphasis";
 | 
						|
  dev->opt[OPT_IMAGE_EMPHASIS].title = SANE_I18N ("Image emphasis");
 | 
						|
  dev->opt[OPT_IMAGE_EMPHASIS].desc = SANE_I18N ("Sets the image emphasis");
 | 
						|
  dev->opt[OPT_IMAGE_EMPHASIS].type = SANE_TYPE_STRING;
 | 
						|
  dev->opt[OPT_IMAGE_EMPHASIS].size =
 | 
						|
    max_string_size (go_image_emphasis_list);
 | 
						|
  dev->opt[OPT_IMAGE_EMPHASIS].constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | 
						|
  dev->opt[OPT_IMAGE_EMPHASIS].constraint.string_list =
 | 
						|
    go_image_emphasis_list;
 | 
						|
  dev->val[OPT_IMAGE_EMPHASIS].s = strdup (SANE_I18N ("medium"));
 | 
						|
 | 
						|
  /* Gamma */
 | 
						|
  dev->opt[OPT_GAMMA].name = "gamma";
 | 
						|
  dev->opt[OPT_GAMMA].title = SANE_I18N ("Gamma");
 | 
						|
  dev->opt[OPT_GAMMA].desc = SANE_I18N ("Gamma");
 | 
						|
  dev->opt[OPT_GAMMA].type = SANE_TYPE_STRING;
 | 
						|
  dev->opt[OPT_GAMMA].size = max_string_size (go_gamma_list);
 | 
						|
  dev->opt[OPT_GAMMA].constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | 
						|
  dev->opt[OPT_GAMMA].constraint.string_list = go_gamma_list;
 | 
						|
  dev->val[OPT_GAMMA].s = strdup (go_gamma_list[0]);
 | 
						|
 | 
						|
  /* Lamp color dropout */
 | 
						|
  dev->opt[OPT_LAMP].name = "lamp-color";
 | 
						|
  dev->opt[OPT_LAMP].title = SANE_I18N ("Lamp color");
 | 
						|
  dev->opt[OPT_LAMP].desc = SANE_I18N ("Sets the lamp color (color dropout)");
 | 
						|
  dev->opt[OPT_LAMP].type = SANE_TYPE_STRING;
 | 
						|
  dev->opt[OPT_LAMP].size = max_string_size (go_lamp_list);
 | 
						|
  dev->opt[OPT_LAMP].constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | 
						|
  dev->opt[OPT_LAMP].constraint.string_list = go_lamp_list;
 | 
						|
  dev->val[OPT_LAMP].s = strdup (go_lamp_list[0]);
 | 
						|
  if (!dev->support_info.support_lamp)
 | 
						|
    dev->opt[OPT_LAMP].cap |= SANE_CAP_INACTIVE;
 | 
						|
 | 
						|
  /* Inverse image */
 | 
						|
  dev->opt[OPT_INVERSE].name = SANE_NAME_INVERSE;
 | 
						|
  dev->opt[OPT_INVERSE].title = SANE_TITLE_INVERSE;
 | 
						|
  dev->opt[OPT_INVERSE].desc =
 | 
						|
    SANE_I18N ("Inverse image in B/W or halftone mode");
 | 
						|
  dev->opt[OPT_INVERSE].type = SANE_TYPE_BOOL;
 | 
						|
  dev->opt[OPT_INVERSE].unit = SANE_UNIT_NONE;
 | 
						|
  dev->val[OPT_INVERSE].w = SANE_FALSE;
 | 
						|
 | 
						|
  /* Mirror image (left/right flip) */
 | 
						|
  dev->opt[OPT_MIRROR].name = SANE_NAME_MIRROR;
 | 
						|
  dev->opt[OPT_MIRROR].title = SANE_TITLE_MIRROR;
 | 
						|
  dev->opt[OPT_MIRROR].desc = SANE_I18N ("Mirror image (left/right flip)");
 | 
						|
  dev->opt[OPT_MIRROR].type = SANE_TYPE_BOOL;
 | 
						|
  dev->opt[OPT_MIRROR].unit = SANE_UNIT_NONE;
 | 
						|
  dev->val[OPT_MIRROR].w = SANE_FALSE;
 | 
						|
 | 
						|
  /* JPEG Image Compression */
 | 
						|
  dev->opt[OPT_JPEG].name = "jpeg";
 | 
						|
  dev->opt[OPT_JPEG].title = SANE_I18N ("jpeg compression");
 | 
						|
  dev->opt[OPT_JPEG].desc =
 | 
						|
    SANE_I18N
 | 
						|
    ("JPEG Image Compression with Q parameter, '0' - no compression");
 | 
						|
  dev->opt[OPT_JPEG].type = SANE_TYPE_INT;
 | 
						|
  dev->opt[OPT_JPEG].unit = SANE_UNIT_NONE;
 | 
						|
  dev->opt[OPT_JPEG].size = sizeof (SANE_Int);
 | 
						|
  dev->opt[OPT_JPEG].constraint_type = SANE_CONSTRAINT_RANGE;
 | 
						|
  dev->opt[OPT_JPEG].constraint.range = &(go_jpeg_compression_range);
 | 
						|
  dev->val[OPT_JPEG].w = 0;
 | 
						|
 | 
						|
  /* Image Rotation */
 | 
						|
  dev->opt[OPT_ROTATE].name = "rotate";
 | 
						|
  dev->opt[OPT_ROTATE].title = SANE_I18N ("Rotate image clockwise");
 | 
						|
  dev->opt[OPT_ROTATE].desc =
 | 
						|
    SANE_I18N("Request driver to rotate pages by a fixed amount");
 | 
						|
  dev->opt[OPT_ROTATE].type = SANE_TYPE_INT;
 | 
						|
  dev->opt[OPT_ROTATE].unit = SANE_UNIT_NONE;
 | 
						|
  dev->opt[OPT_ROTATE].size = sizeof (SANE_Int);
 | 
						|
  dev->opt[OPT_ROTATE].constraint_type = SANE_CONSTRAINT_RANGE;
 | 
						|
  dev->opt[OPT_ROTATE].constraint.range = &(go_rotate_range);
 | 
						|
  dev->val[OPT_ROTATE].w = 0;
 | 
						|
 | 
						|
  /* Software Deskew */
 | 
						|
  dev->opt[OPT_SWDESKEW].name = "swdeskew";
 | 
						|
  dev->opt[OPT_SWDESKEW].title = SANE_I18N ("Software deskew");
 | 
						|
  dev->opt[OPT_SWDESKEW].desc =
 | 
						|
    SANE_I18N("Request driver to rotate skewed pages digitally");
 | 
						|
  dev->opt[OPT_SWDESKEW].type = SANE_TYPE_BOOL;
 | 
						|
  dev->opt[OPT_SWDESKEW].unit = SANE_UNIT_NONE;
 | 
						|
  dev->val[OPT_SWDESKEW].w = SANE_FALSE;
 | 
						|
 | 
						|
  /* Software Despeckle */
 | 
						|
  dev->opt[OPT_SWDESPECK].name = "swdespeck";
 | 
						|
  dev->opt[OPT_SWDESPECK].title = SANE_I18N ("Software despeckle diameter");
 | 
						|
  dev->opt[OPT_SWDESPECK].desc =
 | 
						|
    SANE_I18N("Maximum diameter of lone dots to remove from scan");
 | 
						|
  dev->opt[OPT_SWDESPECK].type = SANE_TYPE_INT;
 | 
						|
  dev->opt[OPT_SWDESPECK].unit = SANE_UNIT_NONE;
 | 
						|
  dev->opt[OPT_SWDESPECK].size = sizeof (SANE_Int);
 | 
						|
  dev->opt[OPT_SWDESPECK].constraint_type = SANE_CONSTRAINT_RANGE;
 | 
						|
  dev->opt[OPT_SWDESPECK].constraint.range = &(go_swdespeck_range);
 | 
						|
  dev->val[OPT_SWDESPECK].w = 0;
 | 
						|
 | 
						|
  /* Software Derotate */
 | 
						|
  dev->opt[OPT_SWDEROTATE].name = "swderotate";
 | 
						|
  dev->opt[OPT_SWDEROTATE].title = SANE_I18N ("Software derotate");
 | 
						|
  dev->opt[OPT_SWDEROTATE].desc =
 | 
						|
    SANE_I18N("Request driver to detect and correct 90 degree image rotation");
 | 
						|
  dev->opt[OPT_SWDEROTATE].type = SANE_TYPE_BOOL;
 | 
						|
  dev->opt[OPT_SWDEROTATE].unit = SANE_UNIT_NONE;
 | 
						|
  dev->val[OPT_SWDEROTATE].w = SANE_FALSE;
 | 
						|
 | 
						|
  /* Software Autocrop*/
 | 
						|
  dev->opt[OPT_SWCROP].name = "swcrop";
 | 
						|
  dev->opt[OPT_SWCROP].title = SANE_I18N ("Software automatic cropping");
 | 
						|
  dev->opt[OPT_SWCROP].desc =
 | 
						|
    SANE_I18N("Request driver to remove border from pages digitally");
 | 
						|
  dev->opt[OPT_SWCROP].type = SANE_TYPE_BOOL;
 | 
						|
  dev->opt[OPT_SWCROP].unit = SANE_UNIT_NONE;
 | 
						|
  dev->val[OPT_SWCROP].w = SANE_FALSE;
 | 
						|
 | 
						|
  /* Software blank page skip */
 | 
						|
  dev->opt[OPT_SWSKIP].name = "swskip";
 | 
						|
  dev->opt[OPT_SWSKIP].title = SANE_I18N ("Software blank skip percentage");
 | 
						|
  dev->opt[OPT_SWSKIP].desc
 | 
						|
   = SANE_I18N("Request driver to discard pages with low numbers of dark pixels");
 | 
						|
  dev->opt[OPT_SWSKIP].type = SANE_TYPE_FIXED;
 | 
						|
  dev->opt[OPT_SWSKIP].unit = SANE_UNIT_PERCENT;
 | 
						|
  dev->opt[OPT_SWSKIP].constraint_type = SANE_CONSTRAINT_RANGE;
 | 
						|
  dev->opt[OPT_SWSKIP].constraint.range = &(go_swskip_range);
 | 
						|
 | 
						|
  /* Lastly, set the default scan mode. This might change some
 | 
						|
   * values previously set here. */
 | 
						|
  sane_control_option (dev, OPT_PAPER_SIZE, SANE_ACTION_SET_VALUE,
 | 
						|
		       (void *) go_paper_list[default_paper_size_idx], NULL);
 | 
						|
  sane_control_option (dev, OPT_MODE, SANE_ACTION_SET_VALUE,
 | 
						|
		       (void *) go_scan_mode_list[0], NULL);
 | 
						|
 | 
						|
  DBG (DBG_proc, "kv_init_options: exit\n");
 | 
						|
 | 
						|
  dev->option_set = 1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
SANE_Status
 | 
						|
kv_control_option (PKV_DEV dev, SANE_Int option,
 | 
						|
		   SANE_Action action, void *val, SANE_Int * info)
 | 
						|
{
 | 
						|
  SANE_Status status;
 | 
						|
  SANE_Word cap;
 | 
						|
  SANE_String_Const name;
 | 
						|
  int i;
 | 
						|
  SANE_Word value;
 | 
						|
 | 
						|
  DBG (DBG_proc, "sane_control_option: enter, option %s, action %s\n",
 | 
						|
       go_option_name[option], action == SANE_ACTION_GET_VALUE ? "R" : "W");
 | 
						|
 | 
						|
  if (info)
 | 
						|
    {
 | 
						|
      *info = 0;
 | 
						|
    }
 | 
						|
 | 
						|
  if (dev->scanning)
 | 
						|
    {
 | 
						|
      return SANE_STATUS_DEVICE_BUSY;
 | 
						|
    }
 | 
						|
 | 
						|
  if (option < 0 || option >= OPT_NUM_OPTIONS)
 | 
						|
    {
 | 
						|
      return SANE_STATUS_UNSUPPORTED;
 | 
						|
    }
 | 
						|
 | 
						|
  cap = dev->opt[option].cap;
 | 
						|
  if (!SANE_OPTION_IS_ACTIVE (cap))
 | 
						|
    {
 | 
						|
      return SANE_STATUS_UNSUPPORTED;
 | 
						|
    }
 | 
						|
 | 
						|
  name = dev->opt[option].name;
 | 
						|
  if (!name)
 | 
						|
    {
 | 
						|
      name = "(no name)";
 | 
						|
    }
 | 
						|
  if (action == SANE_ACTION_GET_VALUE)
 | 
						|
    {
 | 
						|
      switch (option)
 | 
						|
	{
 | 
						|
	  /* word options */
 | 
						|
	case OPT_NUM_OPTS:
 | 
						|
	case OPT_LONGPAPER:
 | 
						|
	case OPT_LENGTHCTL:
 | 
						|
	case OPT_DBLFEED:
 | 
						|
	case OPT_RESOLUTION:
 | 
						|
	case OPT_TL_Y:
 | 
						|
	case OPT_BR_Y:
 | 
						|
	case OPT_TL_X:
 | 
						|
	case OPT_BR_X:
 | 
						|
	case OPT_BRIGHTNESS:
 | 
						|
	case OPT_CONTRAST:
 | 
						|
	case OPT_DUPLEX:
 | 
						|
	case OPT_LANDSCAPE:
 | 
						|
	case OPT_AUTOMATIC_SEPARATION:
 | 
						|
	case OPT_INVERSE:
 | 
						|
	case OPT_MIRROR:
 | 
						|
	case OPT_FEED_TIMEOUT:
 | 
						|
	case OPT_JPEG:
 | 
						|
	case OPT_ROTATE:
 | 
						|
	case OPT_SWDESKEW:
 | 
						|
	case OPT_SWDESPECK:
 | 
						|
	case OPT_SWDEROTATE:
 | 
						|
	case OPT_SWCROP:
 | 
						|
	case OPT_SWSKIP:
 | 
						|
	case OPT_FIT_TO_PAGE:
 | 
						|
	  *(SANE_Word *) val = dev->val[option].w;
 | 
						|
	  DBG (DBG_error, "opt value = %d\n", *(SANE_Word *) val);
 | 
						|
	  return SANE_STATUS_GOOD;
 | 
						|
 | 
						|
	  /* string options */
 | 
						|
	case OPT_MODE:
 | 
						|
	case OPT_FEEDER_MODE:
 | 
						|
	case OPT_SCAN_SOURCE:
 | 
						|
	case OPT_MANUALFEED:
 | 
						|
	case OPT_HALFTONE_PATTERN:
 | 
						|
	case OPT_PAPER_SIZE:
 | 
						|
	case OPT_AUTOMATIC_THRESHOLD:
 | 
						|
	case OPT_WHITE_LEVEL:
 | 
						|
	case OPT_NOISE_REDUCTION:
 | 
						|
	case OPT_IMAGE_EMPHASIS:
 | 
						|
	case OPT_GAMMA:
 | 
						|
	case OPT_LAMP:
 | 
						|
 | 
						|
	  strcpy (val, dev->val[option].s);
 | 
						|
	  DBG (DBG_error, "opt value = %s\n", (char *) val);
 | 
						|
	  return SANE_STATUS_GOOD;
 | 
						|
 | 
						|
	default:
 | 
						|
	  return SANE_STATUS_UNSUPPORTED;
 | 
						|
	}
 | 
						|
    }
 | 
						|
  else if (action == SANE_ACTION_SET_VALUE)
 | 
						|
    {
 | 
						|
      if (!SANE_OPTION_IS_SETTABLE (cap))
 | 
						|
	{
 | 
						|
	  DBG (DBG_error,
 | 
						|
	       "could not set option %s, not settable\n",
 | 
						|
	       go_option_name[option]);
 | 
						|
	  return SANE_STATUS_INVAL;
 | 
						|
	}
 | 
						|
 | 
						|
      status = sanei_constrain_value (dev->opt + option, val, info);
 | 
						|
      if (status != SANE_STATUS_GOOD)
 | 
						|
	{
 | 
						|
	  DBG (DBG_error, "could not set option, invalid value\n");
 | 
						|
	  return status;
 | 
						|
	}
 | 
						|
 | 
						|
      switch (option)
 | 
						|
	{
 | 
						|
	  /* Side-effect options */
 | 
						|
	case OPT_TL_Y:
 | 
						|
	case OPT_BR_Y:
 | 
						|
	case OPT_RESOLUTION:
 | 
						|
	  if (info)
 | 
						|
	    {
 | 
						|
	      *info |= SANE_INFO_RELOAD_PARAMS;
 | 
						|
	    }
 | 
						|
 | 
						|
	  dev->val[option].w = *(SANE_Word *) val;
 | 
						|
 | 
						|
	  if (option == OPT_RESOLUTION)
 | 
						|
	    {
 | 
						|
	      if (round_to_boundry (&(dev->val[option].w),
 | 
						|
				    dev->support_info.
 | 
						|
				    step_resolution, 100, 600))
 | 
						|
		{
 | 
						|
		  if (info)
 | 
						|
		    {
 | 
						|
		      *info |= SANE_INFO_INEXACT;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	  else if (option == OPT_TL_Y)
 | 
						|
	    {
 | 
						|
	      if (dev->val[option].w > dev->val[OPT_BR_Y].w)
 | 
						|
		{
 | 
						|
		  dev->val[option].w = dev->val[OPT_BR_Y].w;
 | 
						|
		  if (info)
 | 
						|
		    {
 | 
						|
		      *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      if (dev->val[option].w < dev->val[OPT_TL_Y].w)
 | 
						|
		{
 | 
						|
		  dev->val[option].w = dev->val[OPT_TL_Y].w;
 | 
						|
		  if (info)
 | 
						|
		    {
 | 
						|
		      *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
	    }
 | 
						|
 | 
						|
	  DBG (DBG_error,
 | 
						|
	       "option %s, input = %d, value = %d\n",
 | 
						|
	       go_option_name[option], (*(SANE_Word *) val),
 | 
						|
	       dev->val[option].w);
 | 
						|
 | 
						|
	  return SANE_STATUS_GOOD;
 | 
						|
 | 
						|
	  /* The length of X must be rounded (up). */
 | 
						|
	case OPT_TL_X:
 | 
						|
	case OPT_BR_X:
 | 
						|
	  {
 | 
						|
	    SANE_Word xr = dev->val[OPT_RESOLUTION].w;
 | 
						|
	    SANE_Word tl_x = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)) * xr;
 | 
						|
	    SANE_Word br_x = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)) * xr;
 | 
						|
	    value = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)) * xr;	/* XR * W */
 | 
						|
 | 
						|
	    if (option == OPT_TL_X)
 | 
						|
	      {
 | 
						|
		SANE_Word max = KV_PIXEL_MAX * xr - KV_PIXEL_ROUND;
 | 
						|
		if (br_x < max)
 | 
						|
		  max = br_x;
 | 
						|
		if (round_to_boundry (&value, KV_PIXEL_ROUND, 0, max))
 | 
						|
		  {
 | 
						|
		    if (info)
 | 
						|
		      {
 | 
						|
			*info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT;
 | 
						|
		      }
 | 
						|
		  }
 | 
						|
	      }
 | 
						|
	    else
 | 
						|
	      {
 | 
						|
		if (round_to_boundry
 | 
						|
		    (&value, KV_PIXEL_ROUND, tl_x, KV_PIXEL_MAX * xr))
 | 
						|
		  {
 | 
						|
		    if (info)
 | 
						|
		      {
 | 
						|
			*info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT;
 | 
						|
		      }
 | 
						|
		  }
 | 
						|
	      }
 | 
						|
 | 
						|
	    dev->val[option].w = SANE_FIX (iluToMm ((double) value / xr));
 | 
						|
 | 
						|
	    if (info)
 | 
						|
	      {
 | 
						|
		*info |= SANE_INFO_RELOAD_PARAMS;
 | 
						|
	      }
 | 
						|
 | 
						|
	    DBG (DBG_error,
 | 
						|
		 "option %s, input = %d, value = %d\n",
 | 
						|
		 go_option_name[option], (*(SANE_Word *) val),
 | 
						|
		 dev->val[option].w);
 | 
						|
	    return SANE_STATUS_GOOD;
 | 
						|
	  }
 | 
						|
	case OPT_LANDSCAPE:
 | 
						|
	  dev->val[option].w = *(SANE_Word *) val;
 | 
						|
	  if (info)
 | 
						|
	    {
 | 
						|
	      *info |= SANE_INFO_RELOAD_PARAMS;
 | 
						|
	    }
 | 
						|
	  return SANE_STATUS_GOOD;
 | 
						|
 | 
						|
	  /* Side-effect free options */
 | 
						|
	case OPT_CONTRAST:
 | 
						|
	case OPT_BRIGHTNESS:
 | 
						|
	case OPT_DUPLEX:
 | 
						|
	case OPT_LONGPAPER:
 | 
						|
	case OPT_LENGTHCTL:
 | 
						|
	case OPT_DBLFEED:
 | 
						|
	case OPT_INVERSE:
 | 
						|
	case OPT_MIRROR:
 | 
						|
	case OPT_AUTOMATIC_SEPARATION:
 | 
						|
	case OPT_JPEG:
 | 
						|
	case OPT_ROTATE:
 | 
						|
	case OPT_SWDESKEW:
 | 
						|
	case OPT_SWDESPECK:
 | 
						|
	case OPT_SWDEROTATE:
 | 
						|
	case OPT_SWCROP:
 | 
						|
	case OPT_SWSKIP:
 | 
						|
	case OPT_FIT_TO_PAGE:
 | 
						|
	  dev->val[option].w = *(SANE_Word *) val;
 | 
						|
	  return SANE_STATUS_GOOD;
 | 
						|
 | 
						|
	case OPT_FEED_TIMEOUT:
 | 
						|
	  dev->val[option].w = *(SANE_Word *) val;
 | 
						|
	  return CMD_set_timeout (dev, *(SANE_Word *) val);
 | 
						|
 | 
						|
	  /* String mode */
 | 
						|
	case OPT_SCAN_SOURCE:
 | 
						|
	case OPT_WHITE_LEVEL:
 | 
						|
	case OPT_NOISE_REDUCTION:
 | 
						|
	case OPT_IMAGE_EMPHASIS:
 | 
						|
	case OPT_GAMMA:
 | 
						|
	case OPT_LAMP:
 | 
						|
	case OPT_HALFTONE_PATTERN:
 | 
						|
	case OPT_FEEDER_MODE:
 | 
						|
	  if (strcmp (dev->val[option].s, val) == 0)
 | 
						|
	    return SANE_STATUS_GOOD;
 | 
						|
	  free (dev->val[option].s);
 | 
						|
	  dev->val[option].s = (SANE_String) strdup (val);
 | 
						|
 | 
						|
	  if (option == OPT_FEEDER_MODE &&
 | 
						|
	      get_string_list_index (go_feeder_mode_list,
 | 
						|
				     dev->val[option].s) == 1)
 | 
						|
	    /* continuous mode */
 | 
						|
	    {
 | 
						|
	      free (dev->val[OPT_SCAN_SOURCE].s);
 | 
						|
	      dev->val[OPT_SCAN_SOURCE].s = strdup (go_scan_source_list[0]);
 | 
						|
	      dev->opt[OPT_LONGPAPER].cap &= ~SANE_CAP_INACTIVE;
 | 
						|
	      if (info)
 | 
						|
		*info |= SANE_INFO_RELOAD_OPTIONS;
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      dev->opt[OPT_LONGPAPER].cap |= SANE_CAP_INACTIVE;
 | 
						|
	      if (info)
 | 
						|
		*info |= SANE_INFO_RELOAD_OPTIONS;
 | 
						|
	    }
 | 
						|
 | 
						|
	  if (option == OPT_SCAN_SOURCE &&
 | 
						|
	      get_string_list_index (go_scan_source_list,
 | 
						|
				     dev->val[option].s) == 1)
 | 
						|
	    /* flatbed */
 | 
						|
	    {
 | 
						|
	      free (dev->val[OPT_FEEDER_MODE].s);
 | 
						|
	      dev->val[OPT_FEEDER_MODE].s = strdup (go_feeder_mode_list[0]);
 | 
						|
	    }
 | 
						|
 | 
						|
	  return SANE_STATUS_GOOD;
 | 
						|
 | 
						|
	case OPT_MODE:
 | 
						|
	  if (strcmp (dev->val[option].s, val) == 0)
 | 
						|
	    return SANE_STATUS_GOOD;
 | 
						|
	  free (dev->val[OPT_MODE].s);
 | 
						|
	  dev->val[OPT_MODE].s = (SANE_String) strdup (val);
 | 
						|
 | 
						|
	  /* Set default options for the scan modes. */
 | 
						|
	  dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
 | 
						|
	  dev->opt[OPT_AUTOMATIC_THRESHOLD].cap |= SANE_CAP_INACTIVE;
 | 
						|
	  dev->opt[OPT_AUTOMATIC_SEPARATION].cap |= SANE_CAP_INACTIVE;
 | 
						|
	  dev->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE;
 | 
						|
	  dev->opt[OPT_INVERSE].cap |= SANE_CAP_INACTIVE;
 | 
						|
	  dev->opt[OPT_JPEG].cap &= ~SANE_CAP_INACTIVE;
 | 
						|
 | 
						|
	  if (strcmp (dev->val[OPT_MODE].s, go_scan_mode_list[0]) == 0)
 | 
						|
	    /* binary */
 | 
						|
	    {
 | 
						|
	      dev->opt[OPT_AUTOMATIC_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
 | 
						|
	      dev->opt[OPT_INVERSE].cap &= ~SANE_CAP_INACTIVE;
 | 
						|
	      dev->opt[OPT_JPEG].cap |= SANE_CAP_INACTIVE;
 | 
						|
	    }
 | 
						|
	  else if (strcmp (dev->val[OPT_MODE].s, go_scan_mode_list[1]) == 0)
 | 
						|
	    /* halftone */
 | 
						|
	    {
 | 
						|
	      dev->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE;
 | 
						|
	      dev->opt[OPT_AUTOMATIC_SEPARATION].cap &= ~SANE_CAP_INACTIVE;
 | 
						|
	      dev->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE;
 | 
						|
	      dev->opt[OPT_INVERSE].cap &= ~SANE_CAP_INACTIVE;
 | 
						|
	      dev->opt[OPT_JPEG].cap |= SANE_CAP_INACTIVE;
 | 
						|
	    }
 | 
						|
	  else if (strcmp (dev->val[OPT_MODE].s, go_scan_mode_list[2]) == 0)
 | 
						|
	    /* grayscale */
 | 
						|
	    {
 | 
						|
	      dev->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE;
 | 
						|
	    }
 | 
						|
 | 
						|
	  if (info)
 | 
						|
	    {
 | 
						|
	      *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
 | 
						|
	    }
 | 
						|
 | 
						|
	  return SANE_STATUS_GOOD;
 | 
						|
 | 
						|
	case OPT_MANUALFEED:
 | 
						|
	  if (strcmp (dev->val[option].s, val) == 0)
 | 
						|
	    return SANE_STATUS_GOOD;
 | 
						|
	  free (dev->val[option].s);
 | 
						|
	  dev->val[option].s = (SANE_String) strdup (val);
 | 
						|
 | 
						|
	  if (strcmp (dev->val[option].s, go_manual_feed_list[0]) == 0)	/* off */
 | 
						|
	    dev->opt[OPT_FEED_TIMEOUT].cap |= SANE_CAP_INACTIVE;
 | 
						|
	  else
 | 
						|
	    dev->opt[OPT_FEED_TIMEOUT].cap &= ~SANE_CAP_INACTIVE;
 | 
						|
	  if (info)
 | 
						|
	    *info |= SANE_INFO_RELOAD_OPTIONS;
 | 
						|
 | 
						|
	  return SANE_STATUS_GOOD;
 | 
						|
 | 
						|
	case OPT_PAPER_SIZE:
 | 
						|
	  if (strcmp (dev->val[option].s, val) == 0)
 | 
						|
	    return SANE_STATUS_GOOD;
 | 
						|
 | 
						|
	  free (dev->val[OPT_PAPER_SIZE].s);
 | 
						|
	  dev->val[OPT_PAPER_SIZE].s = (SANE_Char *) strdup (val);
 | 
						|
 | 
						|
	  i = get_string_list_index (go_paper_list,
 | 
						|
				     dev->val[OPT_PAPER_SIZE].s);
 | 
						|
	  if (i == 0)
 | 
						|
	    {			/*user def */
 | 
						|
	      dev->opt[OPT_TL_X].cap &=
 | 
						|
		dev->opt[OPT_TL_Y].cap &=
 | 
						|
		dev->opt[OPT_BR_X].cap &=
 | 
						|
		dev->opt[OPT_BR_Y].cap &= ~SANE_CAP_INACTIVE;
 | 
						|
	      dev->opt[OPT_LANDSCAPE].cap |= SANE_CAP_INACTIVE;
 | 
						|
	      dev->val[OPT_LANDSCAPE].w = 0;
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      dev->opt[OPT_TL_X].cap |=
 | 
						|
		dev->opt[OPT_TL_Y].cap |=
 | 
						|
		dev->opt[OPT_BR_X].cap |=
 | 
						|
		dev->opt[OPT_BR_Y].cap |= SANE_CAP_INACTIVE;
 | 
						|
	      if (i == 4 || i == 5 || i == 7)
 | 
						|
		{		/*A5, A6 or B6 */
 | 
						|
		  dev->opt[OPT_LANDSCAPE].cap &= ~SANE_CAP_INACTIVE;
 | 
						|
		}
 | 
						|
	      else
 | 
						|
		{
 | 
						|
		  dev->opt[OPT_LANDSCAPE].cap |= SANE_CAP_INACTIVE;
 | 
						|
		  dev->val[OPT_LANDSCAPE].w = 0;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
 | 
						|
	  if (info)
 | 
						|
	    *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
 | 
						|
 | 
						|
	  return SANE_STATUS_GOOD;
 | 
						|
 | 
						|
 | 
						|
	case OPT_AUTOMATIC_THRESHOLD:
 | 
						|
	  if (strcmp (dev->val[option].s, val) == 0)
 | 
						|
	    return SANE_STATUS_GOOD;
 | 
						|
 | 
						|
	  free (dev->val[option].s);
 | 
						|
	  dev->val[option].s = (SANE_Char *) strdup (val);
 | 
						|
 | 
						|
	  /* If the threshold is not set to none, some option must
 | 
						|
	   * disappear. */
 | 
						|
 | 
						|
	  dev->opt[OPT_WHITE_LEVEL].cap |= SANE_CAP_INACTIVE;
 | 
						|
	  dev->opt[OPT_NOISE_REDUCTION].cap |= SANE_CAP_INACTIVE;
 | 
						|
	  dev->opt[OPT_IMAGE_EMPHASIS].cap |= SANE_CAP_INACTIVE;
 | 
						|
	  dev->opt[OPT_AUTOMATIC_SEPARATION].cap |= SANE_CAP_INACTIVE;
 | 
						|
	  dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
 | 
						|
 | 
						|
	  if (strcmp (val, go_automatic_threshold_list[0]) == 0)
 | 
						|
	    {
 | 
						|
	      dev->opt[OPT_WHITE_LEVEL].cap &= ~SANE_CAP_INACTIVE;
 | 
						|
	      dev->opt[OPT_NOISE_REDUCTION].cap &= ~SANE_CAP_INACTIVE;
 | 
						|
	      dev->opt[OPT_IMAGE_EMPHASIS].cap &= ~SANE_CAP_INACTIVE;
 | 
						|
	      dev->opt[OPT_AUTOMATIC_SEPARATION].cap &= ~SANE_CAP_INACTIVE;
 | 
						|
	      if (strcmp (dev->val[OPT_MODE].s, go_scan_mode_list[1]) == 0)
 | 
						|
		{
 | 
						|
		  dev->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
 | 
						|
	  if (info)
 | 
						|
	    {
 | 
						|
	      *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
 | 
						|
	    }
 | 
						|
	  return SANE_STATUS_GOOD;
 | 
						|
 | 
						|
	default:
 | 
						|
	  return SANE_STATUS_INVAL;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  DBG (DBG_proc, "sane_control_option: exit, bad\n");
 | 
						|
 | 
						|
  return SANE_STATUS_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
/* Display a buffer in the log. */
 | 
						|
void
 | 
						|
hexdump (int level, const char *comment, unsigned char *p, int l)
 | 
						|
{
 | 
						|
  int i;
 | 
						|
  char line[128];
 | 
						|
  char *ptr;
 | 
						|
 | 
						|
  DBG (level, "%s\n", comment);
 | 
						|
  ptr = line;
 | 
						|
  for (i = 0; i < l; i++, p++)
 | 
						|
    {
 | 
						|
      if ((i % 16) == 0)
 | 
						|
	{
 | 
						|
	  if (ptr != line)
 | 
						|
	    {
 | 
						|
	      *ptr = '\0';
 | 
						|
	      DBG (level, "%s\n", line);
 | 
						|
	      ptr = line;
 | 
						|
	    }
 | 
						|
	  sprintf (ptr, "%3.3d:", i);
 | 
						|
	  ptr += 4;
 | 
						|
	}
 | 
						|
      sprintf (ptr, " %2.2x", *p);
 | 
						|
      ptr += 3;
 | 
						|
    }
 | 
						|
  *ptr = '\0';
 | 
						|
  DBG (level, "%s\n", line);
 | 
						|
}
 | 
						|
 | 
						|
/* Set window data */
 | 
						|
void
 | 
						|
kv_set_window_data (PKV_DEV dev,
 | 
						|
		    KV_SCAN_MODE scan_mode,
 | 
						|
		    int side, unsigned char *windowdata)
 | 
						|
{
 | 
						|
  int paper = go_paper_val[get_string_list_index (go_paper_list,
 | 
						|
						  dev->val[OPT_PAPER_SIZE].
 | 
						|
						  s)];
 | 
						|
 | 
						|
  /* Page side */
 | 
						|
  windowdata[0] = side;
 | 
						|
 | 
						|
  /* X and Y resolution */
 | 
						|
  Ito16 (dev->val[OPT_RESOLUTION].w, &windowdata[2]);
 | 
						|
  Ito16 (dev->val[OPT_RESOLUTION].w, &windowdata[4]);
 | 
						|
 | 
						|
  /* Width and length */
 | 
						|
  if (paper == 0)
 | 
						|
    {				/* Non-standard document */
 | 
						|
      int x_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w));
 | 
						|
      int y_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_Y].w));
 | 
						|
      int x_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w));
 | 
						|
      int y_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_Y].w));
 | 
						|
      int width = x_br - x_tl;
 | 
						|
      int length = y_br - y_tl;
 | 
						|
      /* Upper Left (X,Y) */
 | 
						|
      Ito32 (x_tl, &windowdata[6]);
 | 
						|
      Ito32 (y_tl, &windowdata[10]);
 | 
						|
 | 
						|
      Ito32 (width, &windowdata[14]);
 | 
						|
      Ito32 (length, &windowdata[18]);
 | 
						|
      Ito32 (width, &windowdata[48]);	/* device specific */
 | 
						|
      Ito32 (length, &windowdata[52]);	/* device specific */
 | 
						|
    }
 | 
						|
 | 
						|
  /* Brightness */
 | 
						|
  windowdata[22] = 255 - GET_OPT_VAL_W (dev, OPT_BRIGHTNESS);
 | 
						|
  windowdata[23] = windowdata[22];	/* threshold, same as brightness. */
 | 
						|
 | 
						|
  /* Contrast */
 | 
						|
  windowdata[24] = GET_OPT_VAL_W (dev, OPT_CONTRAST);
 | 
						|
 | 
						|
  /* Image Composition */
 | 
						|
  windowdata[25] = (unsigned char) scan_mode;
 | 
						|
 | 
						|
  /* Depth */
 | 
						|
  windowdata[26] = kv_get_depth (scan_mode);
 | 
						|
 | 
						|
  /* Halftone pattern. */
 | 
						|
  if (scan_mode == SM_DITHER)
 | 
						|
    {
 | 
						|
      windowdata[28] = GET_OPT_VAL_L (dev, OPT_HALFTONE_PATTERN,
 | 
						|
				      halftone_pattern);
 | 
						|
    }
 | 
						|
 | 
						|
  /* Inverse */
 | 
						|
  if (scan_mode == SM_BINARY || scan_mode == SM_DITHER)
 | 
						|
    {
 | 
						|
      windowdata[29] = GET_OPT_VAL_W (dev, OPT_INVERSE);
 | 
						|
    }
 | 
						|
 | 
						|
  /* Bit ordering */
 | 
						|
  windowdata[31] = 1;
 | 
						|
 | 
						|
  /*Compression Type */
 | 
						|
  if (!(dev->opt[OPT_JPEG].cap & SANE_CAP_INACTIVE)
 | 
						|
      && GET_OPT_VAL_W (dev, OPT_JPEG))
 | 
						|
    {
 | 
						|
      windowdata[32] = 0x81;	/*jpeg */
 | 
						|
      /*Compression Argument */
 | 
						|
      windowdata[33] = GET_OPT_VAL_W (dev, OPT_JPEG);
 | 
						|
    }
 | 
						|
 | 
						|
  /* Gamma */
 | 
						|
  if (scan_mode == SM_DITHER || scan_mode == SM_GRAYSCALE)
 | 
						|
    {
 | 
						|
      windowdata[44] = GET_OPT_VAL_L (dev, OPT_GAMMA, gamma);
 | 
						|
    }
 | 
						|
 | 
						|
  /* Feeder mode */
 | 
						|
  windowdata[57] = GET_OPT_VAL_L (dev, OPT_FEEDER_MODE, feeder_mode);
 | 
						|
 | 
						|
  /* Stop skew -- disabled */
 | 
						|
  windowdata[41] = 0;
 | 
						|
 | 
						|
  /* Scan source */
 | 
						|
  if (GET_OPT_VAL_L (dev, OPT_SCAN_SOURCE, scan_source))
 | 
						|
    {				/* flatbed */
 | 
						|
      windowdata[41] |= 0x80;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      windowdata[41] &= 0x7f;
 | 
						|
    }
 | 
						|
 | 
						|
  /* Paper size */
 | 
						|
  windowdata[47] = paper;
 | 
						|
 | 
						|
  if (paper)			/* Standard Document */
 | 
						|
    windowdata[47] |= 1 << 7;
 | 
						|
 | 
						|
  /* Long paper */
 | 
						|
  if (GET_OPT_VAL_W (dev, OPT_LONGPAPER))
 | 
						|
    {
 | 
						|
      windowdata[47] |= 0x20;
 | 
						|
    }
 | 
						|
 | 
						|
  /* Length control */
 | 
						|
  if (GET_OPT_VAL_W (dev, OPT_LENGTHCTL))
 | 
						|
    {
 | 
						|
      windowdata[47] |= 0x40;
 | 
						|
    }
 | 
						|
 | 
						|
  /* Landscape */
 | 
						|
  if (GET_OPT_VAL_W (dev, OPT_LANDSCAPE))
 | 
						|
    {
 | 
						|
      windowdata[47] |= 1 << 4;
 | 
						|
    }
 | 
						|
  /* Double feed */
 | 
						|
  if (GET_OPT_VAL_W (dev, OPT_DBLFEED))
 | 
						|
    {
 | 
						|
      windowdata[56] = 0x10;
 | 
						|
    }
 | 
						|
 | 
						|
  /* Fit to page */
 | 
						|
  if (GET_OPT_VAL_W (dev, OPT_FIT_TO_PAGE))
 | 
						|
    {
 | 
						|
      windowdata[56] |= 1 << 2;
 | 
						|
    }
 | 
						|
 | 
						|
  /* Manual feed */
 | 
						|
  windowdata[62] = GET_OPT_VAL_L (dev, OPT_MANUALFEED, manual_feed) << 6;
 | 
						|
 | 
						|
  /* Mirror image */
 | 
						|
  if (GET_OPT_VAL_W (dev, OPT_MIRROR))
 | 
						|
    {
 | 
						|
      windowdata[42] = 0x80;
 | 
						|
    }
 | 
						|
 | 
						|
  /* Image emphasis */
 | 
						|
  windowdata[43] = GET_OPT_VAL_L (dev, OPT_IMAGE_EMPHASIS, image_emphasis);
 | 
						|
 | 
						|
  /* White level */
 | 
						|
  windowdata[60] = GET_OPT_VAL_L (dev, OPT_WHITE_LEVEL, white_level);
 | 
						|
 | 
						|
  if (scan_mode == SM_BINARY || scan_mode == SM_DITHER)
 | 
						|
    {
 | 
						|
      /* Noise reduction */
 | 
						|
      windowdata[61] = GET_OPT_VAL_L (dev, OPT_NOISE_REDUCTION,
 | 
						|
				      noise_reduction);
 | 
						|
 | 
						|
      /* Automatic separation */
 | 
						|
      if (scan_mode == SM_DITHER && GET_OPT_VAL_W (dev,
 | 
						|
						   OPT_AUTOMATIC_SEPARATION))
 | 
						|
	{
 | 
						|
	  windowdata[59] = 0x80;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  /* Automatic threshold. Must be last because it may override
 | 
						|
   * some previous options. */
 | 
						|
  if (scan_mode == SM_BINARY)
 | 
						|
    {
 | 
						|
      windowdata[58] =
 | 
						|
	GET_OPT_VAL_L (dev, OPT_AUTOMATIC_THRESHOLD, automatic_threshold);
 | 
						|
    }
 | 
						|
 | 
						|
  if (windowdata[58] != 0)
 | 
						|
    {
 | 
						|
      /* Automatic threshold is enabled. */
 | 
						|
      windowdata[22] = 0;	/* brightness. */
 | 
						|
      windowdata[23] = 0;	/* threshold, same as brightness. */
 | 
						|
      windowdata[24] = 0;	/* contrast */
 | 
						|
      windowdata[27] = windowdata[28] = 0;	/* Halftone pattern. */
 | 
						|
      windowdata[43] = 0;	/* Image emphasis */
 | 
						|
      windowdata[59] = 0;	/* Automatic separation */
 | 
						|
      windowdata[60] = 0;	/* White level */
 | 
						|
      windowdata[61] = 0;	/* Noise reduction */
 | 
						|
    }
 | 
						|
 | 
						|
  /* lamp -- color dropout */
 | 
						|
  windowdata[45] = GET_OPT_VAL_L (dev, OPT_LAMP, lamp) << 4;
 | 
						|
 | 
						|
  /*Stop Mode:    After 1 page */
 | 
						|
  windowdata[63] = 1;
 | 
						|
}
 |