kopia lustrzana https://gitlab.com/sane-project/backends
1582 wiersze
45 KiB
C
1582 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 */
|
|
static const int go_paper_max_width = 216; /* US letter */
|
|
|
|
/* 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 ("linier"),
|
|
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 Continous */
|
|
"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;
|
|
}
|