kopia lustrzana https://gitlab.com/sane-project/backends
				
				
				
			
		
			
				
	
	
		
			1420 wiersze
		
	
	
		
			41 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			1420 wiersze
		
	
	
		
			41 KiB
		
	
	
	
		
			C
		
	
	
| /*
 | |
|    Copyright (C) 2009, Panasonic Russia Ltd.
 | |
|    Copyright (C) 2010,2011, m. allan noah
 | |
| */
 | |
| /*
 | |
|    Panasonic KV-S40xx USB-SCSI scanner driver.
 | |
| */
 | |
| 
 | |
| #include "../include/sane/config.h"
 | |
| 
 | |
| #include <string.h>
 | |
| #define DEBUG_DECLARE_ONLY
 | |
| #define BACKEND_NAME kvs40xx
 | |
| 
 | |
| #include "../include/sane/sanei_backend.h"
 | |
| #include "../include/sane/saneopts.h"
 | |
| #include "../include/sane/sanei.h"
 | |
| #include "../include/sane/sanei_config.h"
 | |
| #include "lassert.h"
 | |
| 
 | |
| #include "kvs40xx.h"
 | |
| 
 | |
| #include "../include/sane/sanei_debug.h"
 | |
| 
 | |
| #include <stdlib.h>
 | |
| 
 | |
| static inline unsigned
 | |
| mm2scanner_units (unsigned mm)
 | |
| {
 | |
|   return (mm * 12000 / 254.0 + .5);
 | |
| }
 | |
| static inline unsigned
 | |
| scanner_units2mm (unsigned u)
 | |
| {
 | |
|   return (u * 254.0 / 12000 + .5);
 | |
| }
 | |
| struct restriction
 | |
| {
 | |
|   unsigned ux, uy, ux_pix, uy_pix;
 | |
| };
 | |
| 
 | |
| static struct restriction flatbad = { 14064, 20400, 7031, 63999 };
 | |
| static struct restriction cw = { 14268, 128000, 7133, 63999 };
 | |
| static struct restriction cl = { 10724, 128000, 5361, 63999 };
 | |
| 
 | |
| static inline int
 | |
| check_area (struct scanner *s, unsigned ux,
 | |
| 	    unsigned uy, unsigned bx, unsigned by)
 | |
| {
 | |
|   int fb = !strcmp (s->val[SOURCE].s, SANE_I18N ("fb"));
 | |
|   struct restriction *r = fb ? &flatbad
 | |
|     : (s->id == KV_S4085CL || s->id == KV_S4065CL) ? &cl : &cw;
 | |
|   unsigned res = s->val[RESOLUTION].w;
 | |
|   unsigned w = bx - ux;
 | |
|   unsigned h = by - uy;
 | |
|   unsigned c1 = mm2scanner_units (ux + w);
 | |
|   unsigned c2 = mm2scanner_units (uy + h);
 | |
|   int c = c1 <= r->ux && c1 >= 16 && c2 >= 1 && c2 <= r->uy ? 0 : -1;
 | |
|   if (c)
 | |
|     return c;
 | |
|   if (mm2scanner_units (ux) > r->ux)
 | |
|     return -1;
 | |
|   if (res * mm2scanner_units (ux) / 1200 > r->ux_pix)
 | |
|     return -1;
 | |
| 
 | |
|   if (res * mm2scanner_units (uy) / 1200 > r->uy_pix)
 | |
|     return -1;
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| static size_t
 | |
| max_string_size (const SANE_String_Const strings[])
 | |
| {
 | |
|   size_t size, max_size = 0;
 | |
|   SANE_Int i;
 | |
| 
 | |
|   for (i = 0; strings[i]; ++i)
 | |
|     {
 | |
|       size = strlen (strings[i]) + 1;
 | |
|       if (size > max_size)
 | |
| 	max_size = size;
 | |
|     }
 | |
|   return max_size;
 | |
| }
 | |
| 
 | |
| static SANE_String_Const mode_list[] = {
 | |
|   SANE_VALUE_SCAN_MODE_LINEART,
 | |
|   SANE_VALUE_SCAN_MODE_GRAY,
 | |
|   SANE_VALUE_SCAN_MODE_COLOR,
 | |
|   NULL
 | |
| };
 | |
| static const unsigned mode_val[] = { 0, 2, 5 };
 | |
| static const unsigned bps_val[] = { 1, 8, 24 };
 | |
| 
 | |
| static const SANE_Range resolutions_range = {
 | |
|   100,600,1
 | |
| };
 | |
| 
 | |
| /* List of feeder modes */
 | |
| static SANE_String_Const feeder_mode_list[] = {
 | |
|   SANE_I18N ("single"),
 | |
|   SANE_I18N ("continuous"),
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| /* List of scan sources */
 | |
| static SANE_String_Const source_list[] = {
 | |
|   SANE_I18N ("adf"),
 | |
|   SANE_I18N ("fb"),
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| /* List of manual feed mode */
 | |
| static SANE_String_Const manual_feed_list[] = {
 | |
|   SANE_I18N ("off"),
 | |
|   SANE_I18N ("wait_doc"),
 | |
|   SANE_I18N ("wait_doc_hopper_up"),
 | |
|   SANE_I18N ("wait_key"),
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| /* List of paper sizes */
 | |
| static SANE_String_Const 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 SANE_String_Const paper_list_woA3[] = {
 | |
|   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 unsigned paper_val[] = { 0, 1, 2, 3, 4, 5, 6, 7,
 | |
|   9, 12, 13, 14, 15
 | |
| };
 | |
| 
 | |
| struct paper_size
 | |
| {
 | |
|   int width;
 | |
|   int height;
 | |
| };
 | |
| static const struct paper_size 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 */
 | |
|   {215, 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 */
 | |
|   {215, 355}			/* US Legal */
 | |
| };
 | |
| 
 | |
| #define MIN_WIDTH	48
 | |
| #define MIN_LENGTH	70
 | |
| #define MAX_WIDTH	297
 | |
| #define MAX_LENGTH	432
 | |
| 
 | |
| #define MAX_WIDTH_A4	227
 | |
| #define MAX_LENGTH_A4	432
 | |
| 
 | |
| static SANE_Range tl_x_range = { 0, MAX_WIDTH - MIN_WIDTH, 0 };
 | |
| static SANE_Range tl_y_range = { 0, MAX_LENGTH - MIN_LENGTH, 0 };
 | |
| static SANE_Range br_x_range = { MIN_WIDTH, MAX_WIDTH, 0 };
 | |
| static SANE_Range br_y_range = { MIN_LENGTH, MAX_LENGTH, 0 };
 | |
| 
 | |
| static SANE_Range tl_x_range_A4 = { 0, MAX_WIDTH_A4 - MIN_WIDTH, 0 };
 | |
| static SANE_Range tl_y_range_A4 = { 0, MAX_LENGTH_A4 - MIN_LENGTH, 0 };
 | |
| static SANE_Range br_x_range_A4 = { MIN_WIDTH, MAX_WIDTH_A4, 0 };
 | |
| static SANE_Range br_y_range_A4 = { MIN_LENGTH, MAX_LENGTH_A4, 0 };
 | |
| 
 | |
| static SANE_Range byte_value_range = { 0, 255, 0 };
 | |
| static SANE_Range compression_value_range = { 1, 0x64, 0 };
 | |
| 
 | |
| /* List of image emphasis options, 5 steps */
 | |
| static SANE_String_Const image_emphasis_list[] = {
 | |
|   SANE_I18N ("none"),
 | |
|   SANE_I18N ("low"),
 | |
|   SANE_I18N ("medium"),
 | |
|   SANE_I18N ("high"),
 | |
|   SANE_I18N ("smooth"),
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| /* List of gamma */
 | |
| static SANE_String_Const gamma_list[] = {
 | |
|   SANE_I18N ("normal"),
 | |
|   SANE_I18N ("crt"),
 | |
|   NULL
 | |
| };
 | |
| static unsigned gamma_val[] = { 0, 1 };
 | |
| 
 | |
| /* List of lamp color dropout */
 | |
| static SANE_String_Const lamp_list[] = {
 | |
|   SANE_I18N ("normal"),
 | |
|   SANE_I18N ("red"),
 | |
|   SANE_I18N ("green"),
 | |
|   SANE_I18N ("blue"),
 | |
|   NULL
 | |
| };
 | |
| static SANE_String_Const dfeed_sence_list[] = {
 | |
|   SANE_I18N ("Normal"),
 | |
|   SANE_I18N ("High sensitivity"),
 | |
|   SANE_I18N ("Low sensitivity"),
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| /* Lists of supported halftone. They are only valid with
 | |
|  * for the Black&White mode. */
 | |
| static SANE_String_Const halftone_pattern[] = {
 | |
|   SANE_I18N ("bayer_64"),
 | |
|   SANE_I18N ("bayer_16"),
 | |
|   SANE_I18N ("halftone_32"),
 | |
|   SANE_I18N ("halftone_64"),
 | |
|   SANE_I18N ("err_diffusion"),
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| /*  Stapled document */
 | |
| static SANE_String_Const stapeled_list[] = {
 | |
|   SANE_I18N ("No detection"),
 | |
|   SANE_I18N ("Normal mode"),
 | |
|   SANE_I18N ("Enhanced mode"),
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| 
 | |
| /* List of automatic threshold options */
 | |
| static SANE_String_Const automatic_threshold_list[] = {
 | |
|   SANE_I18N ("normal"),
 | |
|   SANE_I18N ("light"),
 | |
|   SANE_I18N ("dark"),
 | |
|   NULL
 | |
| };
 | |
| static const int automatic_threshold_val[] = {
 | |
|   0,
 | |
|   0x11,
 | |
|   0x1f
 | |
| };
 | |
| 
 | |
| /* List of white level base. */
 | |
| static SANE_String_Const white_level_list[] = {
 | |
|   SANE_I18N ("From scanner"),
 | |
|   SANE_I18N ("From paper"),
 | |
|   SANE_I18N ("Automatic"),
 | |
|   NULL
 | |
| };
 | |
| static const int white_level_val[] = {
 | |
|   0x00,
 | |
|   0x80,
 | |
|   0x81
 | |
| };
 | |
| 
 | |
| /* List of noise reduction options. */
 | |
| static SANE_String_Const noise_reduction_list[] = {
 | |
|   SANE_I18N ("default"),
 | |
|   "1x1",
 | |
|   "2x2",
 | |
|   "3x3",
 | |
|   "4x4",
 | |
|   "5x5",
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| /* Reset the options for that scanner. */
 | |
| void
 | |
| kvs40xx_init_options (struct scanner *s)
 | |
| {
 | |
|   int i;
 | |
|   SANE_Option_Descriptor *o;
 | |
|   /* Pre-initialize the options. */
 | |
|   memset (s->opt, 0, sizeof (s->opt));
 | |
|   memset (s->val, 0, sizeof (s->val));
 | |
| 
 | |
|   for (i = 0; i < NUM_OPTIONS; i++)
 | |
|     {
 | |
|       s->opt[i].size = sizeof (SANE_Word);
 | |
|       s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
 | |
|     }
 | |
| 
 | |
|   /* Number of options. */
 | |
|   o = &s->opt[NUM_OPTS];
 | |
|   o->name = "";
 | |
|   o->title = SANE_TITLE_NUM_OPTIONS;
 | |
|   o->desc = SANE_DESC_NUM_OPTIONS;
 | |
|   o->type = SANE_TYPE_INT;
 | |
|   o->cap = SANE_CAP_SOFT_DETECT;
 | |
|   s->val[NUM_OPTS].w = NUM_OPTIONS;
 | |
| 
 | |
|   /* Mode group */
 | |
|   o = &s->opt[MODE_GROUP];
 | |
|   o->title = SANE_I18N ("Scan Mode");
 | |
|   o->desc = "";			/* not valid for a group */
 | |
|   o->type = SANE_TYPE_GROUP;
 | |
|   o->cap = 0;
 | |
|   o->size = 0;
 | |
|   o->constraint_type = SANE_CONSTRAINT_NONE;
 | |
| 
 | |
|   /* Scanner supported modes */
 | |
|   o = &s->opt[MODE];
 | |
|   o->name = SANE_NAME_SCAN_MODE;
 | |
|   o->title = SANE_TITLE_SCAN_MODE;
 | |
|   o->desc = SANE_DESC_SCAN_MODE;
 | |
|   o->type = SANE_TYPE_STRING;
 | |
|   o->size = max_string_size (mode_list);
 | |
|   o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | |
|   o->constraint.string_list = mode_list;
 | |
|   s->val[MODE].s = malloc (o->size);
 | |
|   strcpy (s->val[MODE].s, mode_list[2]);
 | |
| 
 | |
|   /* X and Y resolution */
 | |
|   o = &s->opt[RESOLUTION];
 | |
|   o->name = SANE_NAME_SCAN_RESOLUTION;
 | |
|   o->title = SANE_TITLE_SCAN_RESOLUTION;
 | |
|   o->desc = SANE_DESC_SCAN_RESOLUTION;
 | |
|   o->type = SANE_TYPE_INT;
 | |
|   o->unit = SANE_UNIT_DPI;
 | |
|   o->constraint_type = SANE_CONSTRAINT_RANGE;
 | |
|   o->constraint.range = &resolutions_range;
 | |
|   s->val[RESOLUTION].w = 100;
 | |
| 
 | |
|   /* Duplex */
 | |
|   o = &s->opt[DUPLEX];
 | |
|   o->name = "duplex";
 | |
|   o->title = SANE_I18N ("Duplex");
 | |
|   o->desc = SANE_I18N ("Enable Duplex (Dual-Sided) Scanning");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   s->val[DUPLEX].w = SANE_FALSE;
 | |
| 
 | |
|   /*FIXME
 | |
|      if (!s->support_info.support_duplex)
 | |
|      o->cap |= SANE_CAP_INACTIVE;
 | |
|    */
 | |
| 
 | |
|   /* Feeder mode */
 | |
|   o = &s->opt[FEEDER_MODE];
 | |
|   o->name = "feeder-mode";
 | |
|   o->title = SANE_I18N ("Feeder mode");
 | |
|   o->desc = SANE_I18N ("Sets the feeding mode");
 | |
|   o->type = SANE_TYPE_STRING;
 | |
|   o->size = max_string_size (feeder_mode_list);
 | |
|   o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | |
|   o->constraint.string_list = feeder_mode_list;
 | |
|   s->val[FEEDER_MODE].s = malloc (o->size);
 | |
|   strcpy (s->val[FEEDER_MODE].s, feeder_mode_list[0]);
 | |
| 
 | |
|   /* Scan source */
 | |
|   o = &s->opt[SOURCE];
 | |
|   o->name = SANE_NAME_SCAN_SOURCE;
 | |
|   o->title = SANE_TITLE_SCAN_SOURCE;
 | |
|   o->desc = SANE_DESC_SCAN_SOURCE;
 | |
|   o->type = SANE_TYPE_STRING;
 | |
|   o->size = max_string_size (source_list);
 | |
|   o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | |
|   o->constraint.string_list = source_list;
 | |
|   s->val[SOURCE].s = malloc (o->size);
 | |
|   strcpy (s->val[SOURCE].s, source_list[0]);
 | |
|   if (s->id != KV_S7075C)
 | |
|     o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   /* Length control */
 | |
|   o = &s->opt[LENGTHCTL];
 | |
|   o->name = "length-control";
 | |
|   o->title = SANE_I18N ("Length control mode");
 | |
|   o->desc =
 | |
|     SANE_I18N
 | |
|     ("Length Control Mode causes the scanner to read the shorter of either the length of the actual"
 | |
|      " paper or logical document length");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   s->val[LENGTHCTL].w = SANE_FALSE;
 | |
| 
 | |
|   o = &s->opt[LONG_PAPER];
 | |
|   o->name = "long-paper";
 | |
|   o->title = SANE_I18N ("Long paper mode");
 | |
|   o->desc = SANE_I18N ("Long Paper Mode is a mode that the scanner "
 | |
| 		       "reads the image after it divides long paper "
 | |
| 		       "by the length which is set in Document Size option.");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   s->val[LONG_PAPER].w = SANE_FALSE;
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   /* Manual feed */
 | |
|   o = &s->opt[MANUALFEED];
 | |
|   o->name = "manual-feed";
 | |
|   o->title = SANE_I18N ("Manual feed mode");
 | |
|   o->desc = SANE_I18N ("Sets the manual feed mode");
 | |
|   o->type = SANE_TYPE_STRING;
 | |
|   o->size = max_string_size (manual_feed_list);
 | |
|   o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | |
|   o->constraint.string_list = manual_feed_list;
 | |
|   s->val[MANUALFEED].s = malloc (o->size);
 | |
|   strcpy (s->val[MANUALFEED].s, manual_feed_list[0]);
 | |
| 
 | |
|   /*Manual feed timeout */
 | |
|   o = &s->opt[FEED_TIMEOUT];
 | |
|   o->name = "feed-timeout";
 | |
|   o->title = SANE_I18N ("Manual feed timeout");
 | |
|   o->desc = SANE_I18N ("Sets the manual feed timeout in seconds");
 | |
|   o->type = SANE_TYPE_INT;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   o->size = sizeof (SANE_Int);
 | |
|   o->constraint_type = SANE_CONSTRAINT_RANGE;
 | |
|   o->constraint.range = &(byte_value_range);
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
|   s->val[FEED_TIMEOUT].w = 30;
 | |
| 
 | |
|   /* Double feed */
 | |
|   o = &s->opt[DBLFEED];
 | |
|   o->name = "dfeed";
 | |
|   o->title = SANE_I18N ("Double feed detection");
 | |
|   o->desc = SANE_I18N ("Enable/Disable double feed detection");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   s->val[DBLFEED].w = SANE_FALSE;
 | |
| 
 | |
|   o = &s->opt[DFEED_SENCE];
 | |
|   o->name = "dfeed-sense";
 | |
|   o->title = SANE_I18N ("Double feed detector sensitivity");
 | |
|   o->desc = SANE_I18N ("Set the double feed detector sensitivity");
 | |
|   o->type = SANE_TYPE_STRING;
 | |
|   o->size = max_string_size (dfeed_sence_list);
 | |
|   o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | |
|   o->constraint.string_list = dfeed_sence_list;
 | |
|   s->val[DFEED_SENCE].s = malloc (o->size);
 | |
|   strcpy (s->val[DFEED_SENCE].s, dfeed_sence_list[0]);
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   o = &s->opt[DFSTOP];
 | |
|   o->name = "dfstop";
 | |
|   o->title = SANE_I18N ("Do not stop after double feed detection");
 | |
|   o->desc = SANE_I18N ("Do not stop after double feed detection");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   s->val[DFSTOP].w = SANE_FALSE;
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   o = &s->opt[DFEED_L];
 | |
|   o->name = "dfeed_l";
 | |
|   o->title = SANE_I18N ("Ignore left double feed sensor");
 | |
|   o->desc = SANE_I18N ("Ignore left double feed sensor");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   s->val[DFEED_L].w = SANE_FALSE;
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   o = &s->opt[DFEED_C];
 | |
|   o->name = "dfeed_c";
 | |
|   o->title = SANE_I18N ("Ignore center double feed sensor");
 | |
|   o->desc = SANE_I18N ("Ignore center double feed sensor");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   s->val[DFEED_C].w = SANE_FALSE;
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   o = &s->opt[DFEED_R];
 | |
|   o->name = "dfeed_r";
 | |
|   o->title = SANE_I18N ("Ignore right double feed sensor");
 | |
|   o->desc = SANE_I18N ("Ignore right double feed sensor");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   s->val[DFEED_R].w = SANE_FALSE;
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   /* Fit to page */
 | |
|   o = &s->opt[FIT_TO_PAGE];
 | |
|   o->name = SANE_I18N ("fit-to-page");
 | |
|   o->title = SANE_I18N ("Fit to page");
 | |
|   o->desc = SANE_I18N ("Scanner shrinks image to fit scanned page");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   s->val[FIT_TO_PAGE].w = SANE_FALSE;
 | |
| 
 | |
|   /* Geometry group */
 | |
|   o = &s->opt[GEOMETRY_GROUP];
 | |
|   o->title = SANE_I18N ("Geometry");
 | |
|   o->desc = "";			/* not valid for a group */
 | |
|   o->type = SANE_TYPE_GROUP;
 | |
|   o->cap = 0;
 | |
|   o->size = 0;
 | |
|   o->constraint_type = SANE_CONSTRAINT_NONE;
 | |
| 
 | |
|   /* Paper sizes list */
 | |
|   o = &s->opt[PAPER_SIZE];
 | |
|   o->name = "paper-size";
 | |
|   o->title = SANE_I18N ("Paper size");
 | |
|   o->desc = SANE_I18N ("Physical size of the paper in the ADF");
 | |
|   o->type = SANE_TYPE_STRING;
 | |
|   o->constraint.string_list =
 | |
|     s->id == KV_S4085CL || s->id == KV_S4065CL ? paper_list_woA3 : paper_list;
 | |
| 
 | |
| 
 | |
|   o->size = max_string_size (o->constraint.string_list);
 | |
|   o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | |
|   s->val[PAPER_SIZE].s = malloc (o->size);
 | |
|   strcpy (s->val[PAPER_SIZE].s, SANE_I18N ("A4"));
 | |
| 
 | |
|   /* Landscape */
 | |
|   o = &s->opt[LANDSCAPE];
 | |
|   o->name = "landscape";
 | |
|   o->title = SANE_I18N ("Landscape");
 | |
|   o->desc =
 | |
|     SANE_I18N ("Set paper position : "
 | |
| 	       "true for landscape, false for portrait");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   s->val[LANDSCAPE].w = SANE_FALSE;
 | |
| 
 | |
|   /* Upper left X */
 | |
|   o = &s->opt[TL_X];
 | |
|   o->name = SANE_NAME_SCAN_TL_X;
 | |
|   o->title = SANE_TITLE_SCAN_TL_X;
 | |
|   o->desc = SANE_DESC_SCAN_TL_X;
 | |
|   o->type = SANE_TYPE_INT;
 | |
|   o->unit = SANE_UNIT_MM;
 | |
|   o->constraint_type = SANE_CONSTRAINT_RANGE;
 | |
|   o->constraint.range =
 | |
|     (s->id == KV_S4085CL || s->id == KV_S4065CL)
 | |
|     ? &tl_x_range_A4 : &tl_x_range;
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
|   s->val[TL_X].w = 0;
 | |
| 
 | |
|   /* Upper left Y */
 | |
|   o = &s->opt[TL_Y];
 | |
|   o->name = SANE_NAME_SCAN_TL_Y;
 | |
|   o->title = SANE_TITLE_SCAN_TL_Y;
 | |
|   o->desc = SANE_DESC_SCAN_TL_Y;
 | |
|   o->type = SANE_TYPE_INT;
 | |
|   o->unit = SANE_UNIT_MM;
 | |
|   o->constraint_type = SANE_CONSTRAINT_RANGE;
 | |
|   o->constraint.range =
 | |
|     (s->id == KV_S4085CL || s->id == KV_S4065CL)
 | |
|     ? &tl_y_range_A4 : &tl_y_range;
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
|   s->val[TL_Y].w = 0;
 | |
| 
 | |
|   /* Bottom-right x */
 | |
|   o = &s->opt[BR_X];
 | |
|   o->name = SANE_NAME_SCAN_BR_X;
 | |
|   o->title = SANE_TITLE_SCAN_BR_X;
 | |
|   o->desc = SANE_DESC_SCAN_BR_X;
 | |
|   o->type = SANE_TYPE_INT;
 | |
|   o->unit = SANE_UNIT_MM;
 | |
|   o->constraint_type = SANE_CONSTRAINT_RANGE;
 | |
|   o->constraint.range =
 | |
|     (s->id == KV_S4085CL || s->id == KV_S4065CL)
 | |
|     ? &br_x_range_A4 : &br_x_range;
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
|   s->val[BR_X].w = 210;
 | |
| 
 | |
|   /* Bottom-right y */
 | |
|   o = &s->opt[BR_Y];
 | |
|   o->name = SANE_NAME_SCAN_BR_Y;
 | |
|   o->title = SANE_TITLE_SCAN_BR_Y;
 | |
|   o->desc = SANE_DESC_SCAN_BR_Y;
 | |
|   o->type = SANE_TYPE_INT;
 | |
|   o->unit = SANE_UNIT_MM;
 | |
|   o->constraint_type = SANE_CONSTRAINT_RANGE;
 | |
|   o->constraint.range =
 | |
|     (s->id == KV_S4085CL || s->id == KV_S4065CL)
 | |
|     ? &br_y_range_A4 : &br_y_range;
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
|   s->val[BR_Y].w = 297;
 | |
| 
 | |
|   /* Enhancement group */
 | |
|   o = &s->opt[ADVANCED_GROUP];
 | |
|   o->title = SANE_I18N ("Advanced");
 | |
|   o->desc = "";			/* not valid for a group */
 | |
|   o->type = SANE_TYPE_GROUP;
 | |
|   o->cap = SANE_CAP_ADVANCED;
 | |
|   o->size = 0;
 | |
|   o->constraint_type = SANE_CONSTRAINT_NONE;
 | |
| 
 | |
|   /* Brightness */
 | |
|   o = &s->opt[BRIGHTNESS];
 | |
|   o->name = SANE_NAME_BRIGHTNESS;
 | |
|   o->title = SANE_TITLE_BRIGHTNESS;
 | |
|   o->desc = SANE_DESC_BRIGHTNESS;
 | |
|   o->type = SANE_TYPE_INT;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   o->size = sizeof (SANE_Int);
 | |
|   o->constraint_type = SANE_CONSTRAINT_RANGE;
 | |
|   o->constraint.range = &(byte_value_range);
 | |
|   s->val[BRIGHTNESS].w = 128;
 | |
| 
 | |
|   /* Contrast */
 | |
|   o = &s->opt[CONTRAST];
 | |
|   o->name = SANE_NAME_CONTRAST;
 | |
|   o->title = SANE_TITLE_CONTRAST;
 | |
|   o->desc = SANE_DESC_CONTRAST;
 | |
|   o->type = SANE_TYPE_INT;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   o->size = sizeof (SANE_Int);
 | |
|   o->constraint_type = SANE_CONSTRAINT_RANGE;
 | |
|   o->constraint.range = &(byte_value_range);
 | |
|   s->val[CONTRAST].w = 128;
 | |
| 
 | |
|   /* threshold */
 | |
|   o = &s->opt[THRESHOLD];
 | |
|   o->name = SANE_NAME_THRESHOLD;
 | |
|   o->title = SANE_TITLE_THRESHOLD;
 | |
|   o->desc = SANE_DESC_THRESHOLD;
 | |
|   o->type = SANE_TYPE_INT;
 | |
|   o->size = sizeof (SANE_Int);
 | |
|   o->constraint_type = SANE_CONSTRAINT_RANGE;
 | |
|   o->constraint.range = &(byte_value_range);
 | |
|   s->val[THRESHOLD].w = 128;
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   o = &s->opt[AUTOMATIC_THRESHOLD];
 | |
|   o->name = "athreshold";
 | |
|   o->title = SANE_I18N ("Automatic threshold mode");
 | |
|   o->desc = SANE_I18N ("Sets the automatic threshold mode");
 | |
|   o->type = SANE_TYPE_STRING;
 | |
|   o->size = max_string_size (automatic_threshold_list);
 | |
|   o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | |
|   o->constraint.string_list = automatic_threshold_list;
 | |
|   s->val[AUTOMATIC_THRESHOLD].s = malloc (o->size);
 | |
|   strcpy (s->val[AUTOMATIC_THRESHOLD].s, automatic_threshold_list[0]);
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   /* Image emphasis */
 | |
|   o = &s->opt[IMAGE_EMPHASIS];
 | |
|   o->name = "image-emphasis";
 | |
|   o->title = SANE_I18N ("Image emphasis");
 | |
|   o->desc = SANE_I18N ("Sets the image emphasis");
 | |
|   o->type = SANE_TYPE_STRING;
 | |
|   o->size = max_string_size (image_emphasis_list);
 | |
|   o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | |
|   o->constraint.string_list = image_emphasis_list;
 | |
|   s->val[IMAGE_EMPHASIS].s = malloc (o->size);
 | |
|   strcpy (s->val[IMAGE_EMPHASIS].s, image_emphasis_list[0]);;
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   /* Gamma */
 | |
|   o = &s->opt[GAMMA_CORRECTION];
 | |
|   o->name = "gamma-cor";
 | |
|   o->title = SANE_I18N ("Gamma correction");
 | |
|   o->desc = SANE_I18N ("Gamma correction");
 | |
|   o->type = SANE_TYPE_STRING;
 | |
|   o->size = max_string_size (gamma_list);
 | |
|   o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | |
|   o->constraint.string_list = gamma_list;
 | |
|   s->val[GAMMA_CORRECTION].s = malloc (o->size);
 | |
|   strcpy (s->val[GAMMA_CORRECTION].s, gamma_list[0]);
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   /* Lamp color dropout */
 | |
|   o = &s->opt[LAMP];
 | |
|   o->name = "lamp-color";
 | |
|   o->title = SANE_I18N ("Lamp color");
 | |
|   o->desc = SANE_I18N ("Sets the lamp color (color dropout)");
 | |
|   o->type = SANE_TYPE_STRING;
 | |
|   o->size = max_string_size (lamp_list);
 | |
|   o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | |
|   o->constraint.string_list = lamp_list;
 | |
|   s->val[LAMP].s = malloc (o->size);
 | |
|   strcpy (s->val[LAMP].s, lamp_list[0]);
 | |
| 
 | |
|   /* Inverse image */
 | |
|   o = &s->opt[INVERSE];
 | |
|   o->name = "inverse";
 | |
|   o->title = SANE_I18N ("Inverse Image");
 | |
|   o->desc = SANE_I18N ("Inverse image in B/W mode");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   /* Halftone pattern */
 | |
|   o = &s->opt[HALFTONE_PATTERN];
 | |
|   o->name = SANE_NAME_HALFTONE_PATTERN;
 | |
|   o->title = SANE_TITLE_HALFTONE_PATTERN;
 | |
|   o->desc = SANE_DESC_HALFTONE_PATTERN;
 | |
|   o->type = SANE_TYPE_STRING;
 | |
|   o->size = max_string_size (halftone_pattern);
 | |
|   o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | |
|   o->constraint.string_list = halftone_pattern;
 | |
|   s->val[HALFTONE_PATTERN].s = malloc (o->size);
 | |
|   strcpy (s->val[HALFTONE_PATTERN].s, halftone_pattern[0]);
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   /* JPEG Compression */
 | |
|   o = &s->opt[COMPRESSION];
 | |
|   o->name = "jpeg";
 | |
|   o->title = SANE_I18N ("JPEG compression");
 | |
|   o->desc =
 | |
|     SANE_I18N
 | |
|     ("JPEG compression (your application must be able to uncompress)");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
| 
 | |
|   /* Compression parameter */
 | |
|   o = &s->opt[COMPRESSION_PAR];
 | |
|   o->name = "comp_arg";
 | |
|   o->title = "Compression Argument";
 | |
|   o->desc = "Compression Argument (Q parameter for JPEG)";
 | |
|   o->type = SANE_TYPE_INT;
 | |
|   o->size = sizeof (SANE_Int);
 | |
|   o->constraint_type = SANE_CONSTRAINT_RANGE;
 | |
|   o->constraint.range = &(compression_value_range);
 | |
|   s->val[COMPRESSION_PAR].w = 0x4b;
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   /*  Stapled document */
 | |
|   o = &s->opt[STAPELED_DOC];
 | |
|   o->name = "stapeled_doc";
 | |
|   o->title = SANE_I18N ("Detect stapled document");
 | |
|   o->desc = SANE_I18N ("Detect stapled document");
 | |
|   o->type = SANE_TYPE_STRING;
 | |
|   o->size = max_string_size (stapeled_list);
 | |
|   o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | |
|   o->constraint.string_list = stapeled_list;
 | |
|   s->val[STAPELED_DOC].s = malloc (o->size);
 | |
|   strcpy (s->val[STAPELED_DOC].s, stapeled_list[0]);
 | |
|   if (s->id == KV_S7075C)
 | |
|     o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   /* White level base */
 | |
|   o = &s->opt[WHITE_LEVEL];
 | |
|   o->name = SANE_NAME_WHITE_LEVEL;
 | |
|   o->title = SANE_TITLE_WHITE_LEVEL;
 | |
|   o->desc = SANE_DESC_WHITE_LEVEL;
 | |
|   o->type = SANE_TYPE_STRING;
 | |
|   o->size = max_string_size (white_level_list);
 | |
|   o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | |
|   o->constraint.string_list = white_level_list;
 | |
|   s->val[WHITE_LEVEL].s = malloc (o->size);
 | |
|   strcpy (s->val[WHITE_LEVEL].s, white_level_list[0]);
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   /* Noise reduction */
 | |
|   o = &s->opt[NOISE_REDUCTION];
 | |
|   o->name = "noise-reduction";
 | |
|   o->title = SANE_I18N ("Noise reduction");
 | |
|   o->desc = SANE_I18N ("Reduce the isolated dot noise");
 | |
|   o->type = SANE_TYPE_STRING;
 | |
|   o->size = max_string_size (noise_reduction_list);
 | |
|   o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
 | |
|   o->constraint.string_list = noise_reduction_list;
 | |
|   s->val[NOISE_REDUCTION].s = malloc (o->size);
 | |
|   strcpy (s->val[NOISE_REDUCTION].s, noise_reduction_list[0]);
 | |
|   o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   o = &s->opt[RED_CHROMA];
 | |
|   o->name = "red-chroma";
 | |
|   o->title = SANE_I18N ("chroma of red");
 | |
|   o->desc = SANE_I18N ("Set chroma of red");
 | |
|   o->type = SANE_TYPE_INT;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   o->size = sizeof (SANE_Int);
 | |
|   o->constraint_type = SANE_CONSTRAINT_RANGE;
 | |
|   o->constraint.range = &(byte_value_range);
 | |
|   s->val[RED_CHROMA].w = 0;
 | |
| 
 | |
|   o = &s->opt[BLUE_CHROMA];
 | |
|   o->name = "blue chroma";
 | |
|   o->title = SANE_I18N ("chroma of blue");
 | |
|   o->desc = SANE_I18N ("Set chroma of blue");
 | |
|   o->type = SANE_TYPE_INT;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   o->size = sizeof (SANE_Int);
 | |
|   o->constraint_type = SANE_CONSTRAINT_RANGE;
 | |
|   o->constraint.range = &(byte_value_range);
 | |
|   s->val[BLUE_CHROMA].w = 0;
 | |
| 
 | |
|   o = &s->opt[DESKEW];
 | |
|   o->name = "deskew";
 | |
|   o->title = SANE_I18N ("Skew adjustment");
 | |
|   o->desc = SANE_I18N ("Skew adjustment");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   s->val[DESKEW].w = SANE_FALSE;
 | |
|   if (s->id != KV_S4085CL && s->id != KV_S4085CW)
 | |
|     o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   o = &s->opt[STOP_SKEW];
 | |
|   o->name = "stop-skew";
 | |
|   o->title = SANE_I18N ("Stop scanner if a sheet is skewed");
 | |
|   o->desc = SANE_I18N ("Scanner will stop if a sheet is skewed");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   s->val[STOP_SKEW].w = SANE_FALSE;
 | |
| 
 | |
|   o = &s->opt[CROP];
 | |
|   o->name = "crop";
 | |
|   o->title = SANE_I18N ("Crop actual image area");
 | |
|   o->desc = SANE_I18N ("Scanner will automatically detect image area and crop to it");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   s->val[CROP].w = SANE_FALSE;
 | |
|   if (s->id != KV_S4085CL && s->id != KV_S4085CW)
 | |
|     o->cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
|   o = &s->opt[MIRROR];
 | |
|   o->name = "mirror";
 | |
|   o->title = SANE_I18N ("Mirror image");
 | |
|   o->desc = SANE_I18N ("Left/right mirror image");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   s->val[MIRROR].w = SANE_FALSE;
 | |
| 
 | |
|   o = &s->opt[TOPPOS];
 | |
|   o->name = "toppos";
 | |
|   o->title = SANE_I18N ("Addition of space in top position");
 | |
|   o->desc = SANE_I18N ("Addition of space in top position");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   s->val[TOPPOS].w = SANE_FALSE;
 | |
| 
 | |
|   o = &s->opt[BTMPOS];
 | |
|   o->name = "btmpos";
 | |
|   o->title = SANE_I18N ("Addition of space in bottom position");
 | |
|   o->desc = SANE_I18N ("Addition of space in bottom position");
 | |
|   o->type = SANE_TYPE_BOOL;
 | |
|   o->unit = SANE_UNIT_NONE;
 | |
|   s->val[BTMPOS].w = SANE_FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Lookup a string list from one array and return its index. */
 | |
| static int
 | |
| str_index (const SANE_String_Const * list, SANE_String_Const name)
 | |
| {
 | |
|   int index;
 | |
|   index = 0;
 | |
|   while (list[index])
 | |
|     {
 | |
|       if (!strcmp (list[index], name))
 | |
| 	return (index);
 | |
|       index++;
 | |
|     }
 | |
|   return (-1);			/* not found */
 | |
| }
 | |
| 
 | |
| /* Control option */
 | |
| SANE_Status
 | |
| sane_control_option (SANE_Handle handle, SANE_Int option,
 | |
| 		     SANE_Action action, void *val, SANE_Int * info)
 | |
| {
 | |
|   int i;
 | |
|   SANE_Status status;
 | |
|   SANE_Word cap;
 | |
|   struct scanner *s = (struct scanner *) handle;
 | |
| 
 | |
|   if (info)
 | |
|     *info = 0;
 | |
| 
 | |
|   if (option < 0 || option >= NUM_OPTIONS)
 | |
|     return SANE_STATUS_UNSUPPORTED;
 | |
| 
 | |
|   cap = s->opt[option].cap;
 | |
|   if (!SANE_OPTION_IS_ACTIVE (cap))
 | |
|     return SANE_STATUS_UNSUPPORTED;
 | |
| 
 | |
|   if (action == SANE_ACTION_GET_VALUE)
 | |
|     {
 | |
|       if (s->opt[option].type == SANE_TYPE_STRING)
 | |
| 	{
 | |
| 	  DBG (DBG_INFO,
 | |
| 	       "sane_control_option: reading opt[%d] =  %s\n",
 | |
| 	       option, s->val[option].s);
 | |
| 	  strcpy (val, s->val[option].s);
 | |
| 	}
 | |
|       else
 | |
| 	{
 | |
| 	  *(SANE_Word *) val = s->val[option].w;
 | |
| 	  DBG (DBG_INFO,
 | |
| 	       "sane_control_option: reading opt[%d] =  %d\n",
 | |
| 	       option, s->val[option].w);
 | |
| 	}
 | |
|       return SANE_STATUS_GOOD;
 | |
| 
 | |
|     }
 | |
|   else if (action == SANE_ACTION_SET_VALUE)
 | |
|     {
 | |
|       if (!SANE_OPTION_IS_SETTABLE (cap))
 | |
| 	return SANE_STATUS_INVAL;
 | |
| 
 | |
|       status = sanei_constrain_value (s->opt + option, val, info);
 | |
|       if (status != SANE_STATUS_GOOD)
 | |
| 	return status;
 | |
| 
 | |
|       if (s->opt[option].type == SANE_TYPE_STRING)
 | |
| 	{
 | |
| 	  if (!strcmp (val, s->val[option].s))
 | |
| 	    return SANE_STATUS_GOOD;
 | |
| 	  DBG (DBG_INFO,
 | |
| 	       "sane_control_option: writing opt[%d] =  %s\n",
 | |
| 	       option, (SANE_String_Const) val);
 | |
| 	}
 | |
|       else
 | |
| 	{
 | |
| 	  if (*(SANE_Word *) val == s->val[option].w)
 | |
| 	    return SANE_STATUS_GOOD;
 | |
| 	  DBG (DBG_INFO,
 | |
| 	       "sane_control_option: writing opt[%d] =  %d\n",
 | |
| 	       option, *(SANE_Word *) val);
 | |
| 	}
 | |
| 
 | |
|       switch (option)
 | |
| 	{
 | |
| 	  /* Side-effect options */
 | |
| 	case RESOLUTION:
 | |
| 	  s->val[option].w = *(SANE_Word *) val;
 | |
| 	  if (info)
 | |
| 	    *info |= SANE_INFO_RELOAD_PARAMS;
 | |
| 	  return SANE_STATUS_GOOD;
 | |
| 
 | |
| 	case TL_Y:
 | |
| 	  if ((*(SANE_Word *) val) + MIN_LENGTH <=
 | |
| 	      s->val[BR_Y].w &&
 | |
| 	      !check_area (s, s->val[TL_X].w, *(SANE_Word *) val,
 | |
| 			   s->val[BR_X].w, s->val[BR_Y].w))
 | |
| 	    {
 | |
| 	      s->val[option].w = *(SANE_Word *) val;
 | |
| 	      if (info)
 | |
| 		*info |= SANE_INFO_RELOAD_PARAMS;
 | |
| 	    }
 | |
| 	  else if (info)
 | |
| 	    *info |= SANE_INFO_INEXACT |
 | |
| 	      SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
 | |
| 	  return SANE_STATUS_GOOD;
 | |
| 	case BR_Y:
 | |
| 	  if ((*(SANE_Word *) val) >=
 | |
| 	      s->val[TL_Y].w + MIN_LENGTH
 | |
| 	      && !check_area (s, s->val[TL_X].w, s->val[TL_Y].w,
 | |
| 			      s->val[BR_X].w, *(SANE_Word *) val))
 | |
| 	    {
 | |
| 	      s->val[option].w = *(SANE_Word *) val;
 | |
| 	      if (info)
 | |
| 		*info |= SANE_INFO_RELOAD_PARAMS;
 | |
| 	    }
 | |
| 	  else if (info)
 | |
| 	    *info |= SANE_INFO_INEXACT |
 | |
| 	      SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
 | |
| 	  return SANE_STATUS_GOOD;
 | |
| 
 | |
| 	case TL_X:
 | |
| 	  if ((*(SANE_Word *) val) + MIN_WIDTH <=
 | |
| 	      s->val[BR_X].w &&
 | |
| 	      !check_area (s, *(SANE_Word *) val, s->val[TL_Y].w,
 | |
| 			   s->val[BR_X].w, s->val[BR_Y].w))
 | |
| 	    {
 | |
| 	      s->val[option].w = *(SANE_Word *) val;
 | |
| 	      if (info)
 | |
| 		*info |= SANE_INFO_RELOAD_PARAMS;
 | |
| 	    }
 | |
| 	  else if (info)
 | |
| 	    *info |= SANE_INFO_INEXACT |
 | |
| 	      SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
 | |
| 	  return SANE_STATUS_GOOD;
 | |
| 
 | |
| 	case BR_X:
 | |
| 	  if (*(SANE_Word *) val >=
 | |
| 	      s->val[TL_X].w + MIN_WIDTH
 | |
| 	      && !check_area (s, s->val[TL_X].w, s->val[TL_Y].w,
 | |
| 			      *(SANE_Word *) val, s->val[BR_Y].w))
 | |
| 	    {
 | |
| 	      s->val[option].w = *(SANE_Word *) val;
 | |
| 	      if (info)
 | |
| 		*info |= SANE_INFO_RELOAD_PARAMS;
 | |
| 	    }
 | |
| 	  else if (info)
 | |
| 	    *info |= SANE_INFO_INEXACT |
 | |
| 	      SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
 | |
| 	  return SANE_STATUS_GOOD;
 | |
| 
 | |
| 	case LANDSCAPE:
 | |
| 	  s->val[option].w = *(SANE_Word *) val;
 | |
| 	  if (info)
 | |
| 	    *info |= SANE_INFO_RELOAD_PARAMS;
 | |
| 	  return SANE_STATUS_GOOD;
 | |
| 
 | |
| 	  /* Side-effect free options */
 | |
| 	case CONTRAST:
 | |
| 	case BRIGHTNESS:
 | |
| 	case DUPLEX:
 | |
| 	case LENGTHCTL:
 | |
| 	case LONG_PAPER:
 | |
| 	case FIT_TO_PAGE:
 | |
| 	case THRESHOLD:
 | |
| 	case INVERSE:
 | |
| 	case COMPRESSION_PAR:
 | |
| 	case DFSTOP:
 | |
| 	case DFEED_L:
 | |
| 	case DFEED_C:
 | |
| 	case DFEED_R:
 | |
| 	case STOP_SKEW:
 | |
| 	case DESKEW:
 | |
| 	case MIRROR:
 | |
| 	case CROP:
 | |
| 	case TOPPOS:
 | |
| 	case BTMPOS:
 | |
| 	case RED_CHROMA:
 | |
| 	case BLUE_CHROMA:
 | |
| 	  s->val[option].w = *(SANE_Word *) val;
 | |
| 	  return SANE_STATUS_GOOD;
 | |
| 
 | |
| 	case FEED_TIMEOUT:
 | |
| 	  s->val[option].w = *(SANE_Word *) val;
 | |
| 	  return kvs40xx_set_timeout (s, s->val[option].w);
 | |
| 
 | |
| 	  /* String mode */
 | |
| 	case IMAGE_EMPHASIS:
 | |
| 	case GAMMA_CORRECTION:
 | |
| 	case LAMP:
 | |
| 	case HALFTONE_PATTERN:
 | |
| 	case DFEED_SENCE:
 | |
| 	case AUTOMATIC_THRESHOLD:
 | |
| 	case WHITE_LEVEL:
 | |
| 	case NOISE_REDUCTION:
 | |
| 	  strcpy (s->val[option].s, val);
 | |
| 	  return SANE_STATUS_GOOD;
 | |
| 
 | |
| 	case SOURCE:
 | |
| 	  strcpy (s->val[option].s, val);
 | |
| 	  if (strcmp (s->val[option].s, SANE_I18N ("adf")))
 | |
| 	    {
 | |
| 	      strcpy (s->val[FEEDER_MODE].s, feeder_mode_list[0]);
 | |
| 	      strcpy (s->val[MANUALFEED].s, manual_feed_list[0]);
 | |
| 	      s->val[DUPLEX].w = SANE_FALSE;
 | |
| 	      s->val[DBLFEED].w = SANE_FALSE;
 | |
| 	      s->val[BTMPOS].w = SANE_FALSE;
 | |
| 	      s->val[TOPPOS].w = SANE_FALSE;
 | |
| 	      s->val[STOP_SKEW].w = SANE_FALSE;
 | |
| 	      s->val[LENGTHCTL].w = SANE_FALSE;
 | |
| 	      s->val[LONG_PAPER].w = SANE_FALSE;
 | |
| 	      s->opt[FEEDER_MODE].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[MANUALFEED].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DUPLEX].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DBLFEED].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[BTMPOS].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[TOPPOS].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[STOP_SKEW].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[LENGTHCTL].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[LONG_PAPER].cap |= SANE_CAP_INACTIVE;
 | |
| 	    }
 | |
| 	  else
 | |
| 	    {
 | |
| 	      s->opt[FEEDER_MODE].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[MANUALFEED].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DUPLEX].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DBLFEED].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[BTMPOS].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[TOPPOS].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[STOP_SKEW].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[LENGTHCTL].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[LONG_PAPER].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	    }
 | |
| 	  if (info)
 | |
| 	    *info |= SANE_INFO_RELOAD_OPTIONS;
 | |
| 
 | |
| 	  return SANE_STATUS_GOOD;
 | |
| 
 | |
| 	case FEEDER_MODE:
 | |
| 	  strcpy (s->val[option].s, val);
 | |
| 	  if (strcmp (s->val[option].s, SANE_I18N ("continuous")))
 | |
| 	    {
 | |
| 	      s->opt[LONG_PAPER].cap |= SANE_CAP_INACTIVE;
 | |
| 	    }
 | |
| 	  else
 | |
| 	    {
 | |
| 	      s->opt[LONG_PAPER].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	    }
 | |
| 	  if (info)
 | |
| 	    *info |= SANE_INFO_RELOAD_OPTIONS;
 | |
| 
 | |
| 	  return SANE_STATUS_GOOD;
 | |
| 
 | |
| 	case MODE:
 | |
| 	  strcpy (s->val[option].s, val);
 | |
| 	  if (!strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_LINEART))
 | |
| 	    {
 | |
| 	      s->opt[GAMMA_CORRECTION].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[COMPRESSION].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[COMPRESSION_PAR].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE;
 | |
| 
 | |
| 	      s->opt[AUTOMATIC_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[WHITE_LEVEL].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[NOISE_REDUCTION].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[INVERSE].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[RED_CHROMA].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[BLUE_CHROMA].cap |= SANE_CAP_INACTIVE;
 | |
| 	    }
 | |
| 	  else
 | |
| 	    {
 | |
| 	      s->opt[COMPRESSION].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[COMPRESSION_PAR].cap &= ~SANE_CAP_INACTIVE;
 | |
| 
 | |
| 	      s->opt[THRESHOLD].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[INVERSE].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
 | |
| 
 | |
| 	      s->opt[AUTOMATIC_THRESHOLD].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[WHITE_LEVEL].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[NOISE_REDUCTION].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[RED_CHROMA].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[BLUE_CHROMA].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	    }
 | |
| 
 | |
| 	  if (!strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_GRAY))
 | |
| 	    {
 | |
| 	      s->opt[INVERSE].cap &= ~SANE_CAP_INACTIVE;
 | |
| 
 | |
| 	      s->opt[GAMMA_CORRECTION].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	    }
 | |
| 	  else
 | |
| 	    {
 | |
| 	      s->opt[GAMMA_CORRECTION].cap |= SANE_CAP_INACTIVE;
 | |
| 	    }
 | |
| 
 | |
| 	  if (info)
 | |
| 	    *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
 | |
| 
 | |
| 	  return SANE_STATUS_GOOD;
 | |
| 
 | |
| 	case MANUALFEED:
 | |
| 	  strcpy (s->val[option].s, val);
 | |
| 	  if (strcmp (s->val[option].s, manual_feed_list[0]) == 0)	/* off */
 | |
| 	    s->opt[FEED_TIMEOUT].cap |= SANE_CAP_INACTIVE;
 | |
| 	  else
 | |
| 	    s->opt[FEED_TIMEOUT].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	  if (info)
 | |
| 	    *info |= SANE_INFO_RELOAD_OPTIONS;
 | |
| 
 | |
| 	  return SANE_STATUS_GOOD;
 | |
| 
 | |
| 	case STAPELED_DOC:
 | |
| 	  strcpy (s->val[option].s, val);
 | |
| 	  if (strcmp (s->val[option].s, stapeled_list[0]) == 0)
 | |
| 	    {
 | |
| 	      s->opt[DBLFEED].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFSTOP].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_L].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_C].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_C].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_R].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_SENCE].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	    }
 | |
| 	  else
 | |
| 	    {
 | |
| 	      s->opt[DBLFEED].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFSTOP].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_L].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_C].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_R].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_SENCE].cap |= SANE_CAP_INACTIVE;
 | |
| 	    }
 | |
| 	  if (info)
 | |
| 	    *info |= SANE_INFO_RELOAD_OPTIONS;
 | |
| 
 | |
| 	  return SANE_STATUS_GOOD;
 | |
| 
 | |
| 	case DBLFEED:
 | |
| 	  s->val[option].w = *(SANE_Word *) val;
 | |
| 	  if (!s->val[option].b)
 | |
| 	    {
 | |
| 	      s->opt[DFSTOP].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_L].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_C].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_R].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_SENCE].cap |= SANE_CAP_INACTIVE;
 | |
| 	    }
 | |
| 	  else
 | |
| 	    {
 | |
| 	      s->opt[DFSTOP].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_L].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_C].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_C].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_R].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[DFEED_SENCE].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	    }
 | |
| 	  if (info)
 | |
| 	    *info |= SANE_INFO_RELOAD_OPTIONS;
 | |
| 
 | |
| 	  return SANE_STATUS_GOOD;
 | |
| 
 | |
| 	case PAPER_SIZE:
 | |
| 	  strcpy (s->val[option].s, val);
 | |
| 	  i = str_index (paper_list, s->val[option].s);
 | |
| 	  if (i == 0)
 | |
| 	    {			/*user def */
 | |
| 	      s->opt[TL_X].cap &=
 | |
| 		s->opt[TL_Y].cap &=
 | |
| 		s->opt[BR_X].cap &= s->opt[BR_Y].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	      s->opt[LANDSCAPE].cap |= SANE_CAP_INACTIVE;
 | |
| 	      s->val[LANDSCAPE].w = 0;
 | |
| 	    }
 | |
| 	  else
 | |
| 	    {
 | |
| 	      s->opt[TL_X].cap |=
 | |
| 		s->opt[TL_Y].cap |=
 | |
| 		s->opt[BR_X].cap |= s->opt[BR_Y].cap |= SANE_CAP_INACTIVE;
 | |
| 	      if ( /*i == 4 || */ i == 5 || i == 6 /*XXX*/
 | |
| 		  || i == 10 || i == 11)
 | |
| 		{		/*A4, A5, A6, B5, B6 */
 | |
| 		  if ((s->id == KV_S4085CL || s->id == KV_S4065CL)
 | |
| 		      && i == 4 && i == 10)
 | |
| 		    {		/*A4, B5 */
 | |
| 		      s->opt[LANDSCAPE].cap |= SANE_CAP_INACTIVE;
 | |
| 		      s->val[LANDSCAPE].w = 0;
 | |
| 		    }
 | |
| 		  else
 | |
| 		    s->opt[LANDSCAPE].cap &= ~SANE_CAP_INACTIVE;
 | |
| 		}
 | |
| 	      else
 | |
| 		{
 | |
| 		  s->opt[LANDSCAPE].cap |= SANE_CAP_INACTIVE;
 | |
| 		  s->val[LANDSCAPE].w = 0;
 | |
| 		}
 | |
| 	    }
 | |
| 	  if (info)
 | |
| 	    *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
 | |
| 
 | |
| 	  return SANE_STATUS_GOOD;
 | |
| 
 | |
| 	case COMPRESSION:
 | |
| 	  s->val[option].w = *(SANE_Word *) val;
 | |
| 	  if (!s->val[option].b)
 | |
| 	    {
 | |
| 	      s->opt[COMPRESSION_PAR].cap |= SANE_CAP_INACTIVE;
 | |
| 	    }
 | |
| 	  else
 | |
| 	    {
 | |
| 	      s->opt[COMPRESSION_PAR].cap &= ~SANE_CAP_INACTIVE;
 | |
| 	    }
 | |
| 	  if (info)
 | |
| 	    *info |= SANE_INFO_RELOAD_OPTIONS;
 | |
| 
 | |
| 	  return SANE_STATUS_GOOD;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
| 
 | |
|   return SANE_STATUS_UNSUPPORTED;
 | |
| }
 | |
| 
 | |
| void
 | |
| kvs40xx_init_window (struct scanner *s, struct window *wnd, int wnd_id)
 | |
| {
 | |
|   int paper = str_index (paper_list, s->val[PAPER_SIZE].s), i;
 | |
|   memset (wnd, 0, sizeof (struct window));
 | |
|   copy16 (wnd->window_descriptor_block_length, cpu2be16 (66));
 | |
| 
 | |
|   wnd->window_identifier = wnd_id;
 | |
|   copy16 (wnd->x_resolution, cpu2be16 (s->val[RESOLUTION].w));
 | |
|   copy16 (wnd->y_resolution, cpu2be16 (s->val[RESOLUTION].w));
 | |
|   if (!paper)
 | |
|     {
 | |
|       copy32 (wnd->upper_left_x,
 | |
|               cpu2be32 (mm2scanner_units (s->val[TL_X].w)));
 | |
|       copy32 (wnd->upper_left_y,
 | |
|               cpu2be32 (mm2scanner_units (s->val[TL_Y].w)));
 | |
|       copy32 (wnd->document_width,
 | |
|               cpu2be32 (mm2scanner_units (s->val[BR_X].w)));
 | |
|       copy32 (wnd->width,
 | |
|               cpu2be32 (mm2scanner_units (s->val[BR_X].w - s->val[TL_X].w)));
 | |
|       copy32 (wnd->document_length, cpu2be32 (mm2scanner_units
 | |
|                                               (s->val[BR_Y].w)));
 | |
|       copy32 (wnd->length,
 | |
|               cpu2be32 (mm2scanner_units (s->val[BR_Y].w - s->val[TL_Y].w)));
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       u32 w = cpu2be32 (mm2scanner_units (paper_sizes[paper].width));
 | |
|       u32 h = cpu2be32 (mm2scanner_units (paper_sizes[paper].height));
 | |
|       copy32 (wnd->upper_left_x, cpu2be32 (mm2scanner_units (0)));
 | |
|       copy32 (wnd->upper_left_y, cpu2be32 (mm2scanner_units (0)));
 | |
|       if (!s->val[LANDSCAPE].b)
 | |
| 	{
 | |
| 	  copy32 (wnd->width, w);
 | |
| 	  copy32 (wnd->length, h);
 | |
| 	  copy32 (wnd->document_width, w);
 | |
| 	  copy32 (wnd->document_length, h);
 | |
| 	}
 | |
|       else
 | |
| 	{
 | |
| 	  copy32 (wnd->width, h);
 | |
| 	  copy32 (wnd->length, w);
 | |
| 	  copy32 (wnd->document_width, h);
 | |
| 	  copy32 (wnd->document_length, w);
 | |
| 	}
 | |
|     }
 | |
|   wnd->brightness = s->val[BRIGHTNESS].w;
 | |
|   wnd->threshold = s->val[THRESHOLD].w;
 | |
|   wnd->contrast = s->val[CONTRAST].w;
 | |
|   wnd->image_composition = mode_val[str_index (mode_list, s->val[MODE].s)];
 | |
|   wnd->bit_per_pixel = bps_val[str_index (mode_list, s->val[MODE].s)];
 | |
| 
 | |
|   copy16 (wnd->halftone_pattern,
 | |
|           cpu2be16 (str_index (halftone_pattern, s->val[HALFTONE_PATTERN].s)));
 | |
| 
 | |
|   wnd->rif_padding = s->val[INVERSE].b << 7;
 | |
|   copy16 (wnd->bit_ordering, cpu2be16 (BIT_ORDERING));
 | |
|   wnd->compression_type = s->val[COMPRESSION].b ? 0x81 : 0;
 | |
|   wnd->compression_argument = s->val[COMPRESSION_PAR].w;
 | |
| 
 | |
|   wnd->vendor_unique_identifier = 0;
 | |
|   wnd->nobuf_fstspeed_dfstop = str_index (source_list,
 | |
| 					  s->val[SOURCE].s) << 7 |
 | |
|     str_index (stapeled_list,
 | |
| 	       s->val[STAPELED_DOC].s) << 5 |
 | |
|     s->val[STOP_SKEW].b << 4 | s->val[CROP].b << 3 | s->val[DFSTOP].b << 0;
 | |
| 
 | |
|   wnd->mirror_image = s->val[MIRROR].b << 7 |
 | |
|     s->val[DFEED_L].b << 2 | s->val[DFEED_C].b << 1 | s->val[DFEED_R].b << 0;
 | |
|   wnd->image_emphasis = str_index (image_emphasis_list,
 | |
| 				   s->val[IMAGE_EMPHASIS].s);
 | |
|   wnd->gamma_correction = gamma_val[str_index (gamma_list,
 | |
| 					       s->val[GAMMA_CORRECTION].s)];
 | |
|   wnd->mcd_lamp_dfeed_sens =
 | |
|     str_index (lamp_list, s->val[LAMP].s) << 4 |
 | |
|     str_index (dfeed_sence_list, s->val[DFEED_SENCE].s);
 | |
| 
 | |
|   wnd->document_size = (paper != 0) << 7
 | |
|     | s->val[LENGTHCTL].b << 6
 | |
|     | s->val[LONG_PAPER].b << 5 | s->val[LANDSCAPE].b << 4 | paper_val[paper];
 | |
| 
 | |
|   wnd->ahead_deskew_dfeed_scan_area_fspeed_rshad =
 | |
|     (s->val[DESKEW].b || s->val[CROP].b ? 2 : 0) << 5 | /*XXX*/
 | |
|     s->val[DBLFEED].b << 4 | s->val[FIT_TO_PAGE].b << 2;
 | |
|   wnd->continuous_scanning_pages =
 | |
|     str_index (feeder_mode_list, s->val[FEEDER_MODE].s) ? 0xff : 0;
 | |
|   wnd->automatic_threshold_mode = automatic_threshold_val
 | |
|     [str_index (automatic_threshold_list, s->val[AUTOMATIC_THRESHOLD].s)];
 | |
|   wnd->automatic_separation_mode = 0;	/*Does not supported */
 | |
|   wnd->standard_white_level_mode =
 | |
|     white_level_val[str_index (white_level_list, s->val[WHITE_LEVEL].s)];
 | |
|   wnd->b_wnr_noise_reduction =
 | |
|     str_index (noise_reduction_list, s->val[NOISE_REDUCTION].s);
 | |
| 
 | |
|   i = str_index (manual_feed_list, s->val[MANUALFEED].s);
 | |
|   wnd->mfeed_toppos_btmpos_dsepa_hsepa_dcont_rstkr = i << 6 |
 | |
|     s->val[TOPPOS].b << 5 | s->val[BTMPOS].b << 4;
 | |
|   wnd->stop_mode = 1;
 | |
|   wnd->red_chroma = s->val[RED_CHROMA].w;
 | |
|   wnd->blue_chroma = s->val[BLUE_CHROMA].w;
 | |
| }
 | |
| 
 | |
| /* Get scan parameters */
 | |
| SANE_Status
 | |
| sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
 | |
| {
 | |
|   struct scanner *s = (struct scanner *) handle;
 | |
|   SANE_Parameters *p = &s->params;
 | |
| 
 | |
|   if (!s->scanning)
 | |
|     {
 | |
|       unsigned w, h, res = s->val[RESOLUTION].w;
 | |
|       unsigned i = str_index (paper_list,
 | |
| 			      s->val[PAPER_SIZE].s);
 | |
|       if (i)
 | |
| 	{
 | |
| 	  if (s->val[LANDSCAPE].b)
 | |
| 	    {
 | |
| 	      w = paper_sizes[i].height;
 | |
| 	      h = paper_sizes[i].width;
 | |
| 	    }
 | |
| 	  else
 | |
| 	    {
 | |
| 	      w = paper_sizes[i].width;
 | |
| 	      h = paper_sizes[i].height;
 | |
| 	    }
 | |
| 	}
 | |
|       else
 | |
| 	{
 | |
| 	  w = s->val[BR_X].w - s->val[TL_X].w;
 | |
| 	  h = s->val[BR_Y].w - s->val[TL_Y].w;
 | |
| 	}
 | |
|       p->pixels_per_line = w * res / 25.4 + .5;
 | |
|       p->lines = h * res / 25.4 + .5;
 | |
|     }
 | |
| 
 | |
|   p->format = !strcmp (s->val[MODE].s,
 | |
| 		       SANE_VALUE_SCAN_MODE_COLOR) ? SANE_FRAME_RGB :
 | |
|     SANE_FRAME_GRAY;
 | |
|   p->last_frame = SANE_TRUE;
 | |
|   p->depth = bps_val[str_index (mode_list, s->val[MODE].s)];
 | |
|   p->bytes_per_line = p->depth * p->pixels_per_line / 8;
 | |
|   if (p->depth > 8)
 | |
|     p->depth = 8;
 | |
|   if (params)
 | |
|     memcpy (params, p, sizeof (SANE_Parameters));
 | |
|   s->side_size = p->bytes_per_line * p->lines;
 | |
| 
 | |
|   return SANE_STATUS_GOOD;
 | |
| }
 |