kopia lustrzana https://gitlab.com/sane-project/backends
- added OPT_CUSTOM_GAMMA and OPT_GAMMA_VECTOR* options for GL646
- fixed allocation bugs detected by valgrind - fixed bugs detected by 'tstbackend -r 1 -l 1' - allow 'genesys' as default value for backend opening - made OPT_COLOR_FILTER effectively work for GL646 scanners - split sane_control_options() to make it more readablemerge-requests/1/head
rodzic
0239a8344a
commit
79fbd0c2f1
|
@ -1,3 +1,11 @@
|
|||
2008-04-05 Stéphane Voltz <stef.dev@free.fr>
|
||||
* backend/genesys.c backend/genesys.h backend/genesys_devices.c
|
||||
backend/genesys_gl646.c backend/genesys_low.h:
|
||||
Fixed double free problems, made OPT_COLOR_FILTER work for
|
||||
GL646 scanners, added OPT_CUSTOM_GAMMA and OPT_GAMMA_VECTOR*
|
||||
options, split sane_control_options to make it more readable,
|
||||
fixed 'reset stream' problem for MD6471.
|
||||
|
||||
2008-04-05 Stéphane Voltz <stef.dev@free.fr>
|
||||
* backend/rts8891.c:
|
||||
split sane_control_option() to make it more readable
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Copyright (C) 2003, 2004 Henning Meier-Geinitz <henning@meier-geinitz.de>
|
||||
Copyright (C) 2004, 2005 Gerhard Jaeger <gerhard@gjaeger.de>
|
||||
Copyright (C) 2004, 2007 Stephane Voltz <stef.dev@free.fr>
|
||||
Copyright (C) 2004, 2008 Stéphane Voltz <stef.dev@free.fr>
|
||||
Copyright (C) 2005, 2006 Pierre Willenbrock <pierre@pirsoft.dnsalias.org>
|
||||
Copyright (C) 2006 Laurent Charpentier <laurent_pubs@yahoo.com>
|
||||
Copyright (C) 2007 Luke <iceyfor@gmail.com>
|
||||
|
@ -73,6 +73,8 @@
|
|||
#include "genesys.h"
|
||||
#include "genesys_devices.c"
|
||||
|
||||
#define FREE_IFNOT_NULL(x) if(x!=NULL) { free(x); x=NULL;}
|
||||
|
||||
static SANE_Int num_devices = 0;
|
||||
static Genesys_Device *first_dev = 0;
|
||||
static Genesys_Scanner *first_handle = 0;
|
||||
|
@ -85,10 +87,10 @@ static SANE_Int new_dev_len = 0;
|
|||
static SANE_Int new_dev_alloced = 0;
|
||||
|
||||
static SANE_String_Const mode_list[] = {
|
||||
SANE_I18N ("Color"),
|
||||
SANE_I18N ("Gray"),
|
||||
/* SANE_I18N ("Halftone"), currently unused */
|
||||
SANE_I18N ("Lineart"),
|
||||
SANE_VALUE_SCAN_MODE_COLOR,
|
||||
SANE_VALUE_SCAN_MODE_GRAY,
|
||||
/* SANE_TITLE_HALFTONE, currently unused */
|
||||
SANE_VALUE_SCAN_MODE_LINEART,
|
||||
0
|
||||
};
|
||||
|
||||
|
@ -129,6 +131,24 @@ static const SANE_Range u8_range = {
|
|||
0 /* quantization */
|
||||
};
|
||||
|
||||
static const SANE_Range u12_range = {
|
||||
0, /* minimum */
|
||||
4095, /* maximum */
|
||||
0 /* quantization */
|
||||
};
|
||||
|
||||
static const SANE_Range u14_range = {
|
||||
0, /* minimum */
|
||||
16383, /* maximum */
|
||||
0 /* quantization */
|
||||
};
|
||||
|
||||
static const SANE_Range u16_range = {
|
||||
0, /* minimum */
|
||||
65535, /* maximum */
|
||||
0 /* quantization */
|
||||
};
|
||||
|
||||
static const SANE_Range threshold_percentage_range = {
|
||||
SANE_FIX (0), /* minimum */
|
||||
SANE_FIX (100), /* maximum */
|
||||
|
@ -686,9 +706,11 @@ sanei_genesys_create_slope_table3 (Genesys_Device * dev,
|
|||
vtarget,
|
||||
vstart,
|
||||
vend,
|
||||
dev->motor.slopes[power_mode][step_type].
|
||||
dev->motor.
|
||||
slopes[power_mode][step_type].
|
||||
minimum_steps << step_type,
|
||||
dev->motor.slopes[power_mode][step_type].g,
|
||||
dev->motor.
|
||||
slopes[power_mode][step_type].g,
|
||||
used_steps, &vfinal);
|
||||
|
||||
if (final_exposure)
|
||||
|
@ -719,9 +741,8 @@ genesys_create_slope_table4 (Genesys_Device * dev,
|
|||
|
||||
DBG (DBG_proc,
|
||||
"sanei_genesys_create_slope_table: %d steps, step_type = %d, "
|
||||
"exposure_time = %d, same_speed = %d, yres = %.2f, power_mode = %d\n",
|
||||
steps, step_type,
|
||||
exposure_time, same_speed, yres, power_mode);
|
||||
"exposure_time = %d, same_speed = %d, yres = %.2f, power_mode = %d\n",
|
||||
steps, step_type, exposure_time, same_speed, yres, power_mode);
|
||||
|
||||
/* final speed */
|
||||
vtarget = (exposure_time * yres) / dev->motor.base_ydpi;
|
||||
|
@ -746,9 +767,11 @@ genesys_create_slope_table4 (Genesys_Device * dev,
|
|||
vtarget,
|
||||
vstart,
|
||||
vend,
|
||||
dev->motor.slopes[power_mode][step_type].
|
||||
dev->motor.
|
||||
slopes[power_mode][step_type].
|
||||
minimum_steps << step_type,
|
||||
dev->motor.slopes[power_mode][step_type].g,
|
||||
dev->motor.
|
||||
slopes[power_mode][step_type].g,
|
||||
NULL, NULL);
|
||||
|
||||
DBG (DBG_proc,
|
||||
|
@ -774,9 +797,8 @@ genesys_create_slope_table2 (Genesys_Device * dev,
|
|||
|
||||
DBG (DBG_proc,
|
||||
"sanei_genesys_create_slope_table2: %d steps, step_type = %d, "
|
||||
"exposure_time = %d, same_speed = %d, yres = %.2f, power_mode = %d\n",
|
||||
steps, step_type,
|
||||
exposure_time, same_speed, yres, power_mode);
|
||||
"exposure_time = %d, same_speed = %d, yres = %.2f, power_mode = %d\n",
|
||||
steps, step_type, exposure_time, same_speed, yres, power_mode);
|
||||
|
||||
/* start speed */
|
||||
if (dev->model->motor_type == MOTOR_5345)
|
||||
|
@ -1104,9 +1126,9 @@ sanei_genesys_exposure_time2 (Genesys_Device * dev, float ydpi,
|
|||
int led_exposure, int power_mode)
|
||||
{
|
||||
int exposure_by_ccd = endpixel + 32;
|
||||
int exposure_by_motor =
|
||||
(dev->motor.slopes[power_mode][step_type].maximum_speed
|
||||
*dev->motor.base_ydpi)/ydpi;
|
||||
int exposure_by_motor =
|
||||
(dev->motor.slopes[power_mode][step_type].maximum_speed
|
||||
* dev->motor.base_ydpi) / ydpi;
|
||||
int exposure_by_led = led_exposure;
|
||||
|
||||
int exposure = exposure_by_ccd;
|
||||
|
@ -2201,8 +2223,7 @@ genesys_dark_shading_calibration (Genesys_Device * dev)
|
|||
else
|
||||
channels = 1;
|
||||
|
||||
if (dev->dark_average_data)
|
||||
free (dev->dark_average_data);
|
||||
FREE_IFNOT_NULL (dev->dark_average_data);
|
||||
|
||||
dev->dark_average_data = malloc (channels * 2 * pixels_per_line);
|
||||
if (!dev->dark_average_data)
|
||||
|
@ -2333,8 +2354,7 @@ genesys_dummy_dark_shading (Genesys_Device * dev)
|
|||
else
|
||||
channels = 1;
|
||||
|
||||
if (dev->dark_average_data)
|
||||
free (dev->dark_average_data);
|
||||
FREE_IFNOT_NULL (dev->dark_average_data);
|
||||
|
||||
dev->dark_average_data = malloc (channels * 2 * pixels_per_line);
|
||||
if (!dev->dark_average_data)
|
||||
|
@ -3225,8 +3245,17 @@ genesys_flatbed_calibration (Genesys_Device * dev)
|
|||
if (dev->settings.yres <= dev->sensor.optical_res / 2)
|
||||
yres /= 2;
|
||||
|
||||
/* send default gamma table */
|
||||
status = dev->model->cmd_set->send_gamma_table (dev, 1);
|
||||
/* send custom or generic gamma tables depending on flag */
|
||||
if (dev->model->flags & GENESYS_FLAG_CUSTOM_GAMMA)
|
||||
{
|
||||
/* use custom gamma table */
|
||||
status = dev->model->cmd_set->send_gamma_table (dev, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* send default gamma table if no custom gamma */
|
||||
status = dev->model->cmd_set->send_gamma_table (dev, 1);
|
||||
}
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
|
@ -3412,7 +3441,7 @@ genesys_flatbed_calibration (Genesys_Device * dev)
|
|||
return status;
|
||||
}
|
||||
|
||||
/* send gamma tables if needed */
|
||||
/* send specific gamma tables if needed */
|
||||
status = dev->model->cmd_set->send_gamma_table (dev, 0);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
|
@ -4488,12 +4517,13 @@ calc_parameters (Genesys_Scanner * s)
|
|||
|
||||
s->params.last_frame = SANE_TRUE; /* only single pass scanning supported */
|
||||
|
||||
if (strcmp (mode, "Gray") == 0 || strcmp (mode, "Lineart") == 0)
|
||||
if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0
|
||||
|| strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0)
|
||||
s->params.format = SANE_FRAME_GRAY;
|
||||
else /* Color */
|
||||
s->params.format = SANE_FRAME_RGB;
|
||||
|
||||
if (strcmp (mode, "Lineart") == 0)
|
||||
if (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0)
|
||||
s->params.depth = 1;
|
||||
else
|
||||
s->params.depth = depth;
|
||||
|
@ -4534,11 +4564,11 @@ calc_parameters (Genesys_Scanner * s)
|
|||
if (s->params.format == SANE_FRAME_RGB)
|
||||
s->params.bytes_per_line *= 3;
|
||||
|
||||
if (strcmp (mode, "Color") == 0)
|
||||
if (strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0)
|
||||
s->dev->settings.scan_mode = 4;
|
||||
else if (strcmp (mode, "Gray") == 0)
|
||||
else if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0)
|
||||
s->dev->settings.scan_mode = 2;
|
||||
else if (strcmp (mode, "Halftone") == 0)
|
||||
else if (strcmp (mode, SANE_TITLE_HALFTONE) == 0)
|
||||
s->dev->settings.scan_mode = 1;
|
||||
else /* Lineart */
|
||||
s->dev->settings.scan_mode = 0;
|
||||
|
@ -4584,6 +4614,41 @@ create_bpp_list (Genesys_Scanner * s, SANE_Int * bpp)
|
|||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/* this function initialize a gamma vector based on the ASIC:
|
||||
* gl646: 12 or 14 bits gamma table depending on GENESYS_FLAG_14BIT_GAMMA
|
||||
* gl84x: 16 bits
|
||||
*/
|
||||
static void
|
||||
init_gamma_vector_option (Genesys_Scanner * scanner, int option)
|
||||
{
|
||||
/* the option is inactive until the custom gamma control
|
||||
* is enabled */
|
||||
scanner->opt[option].type = SANE_TYPE_INT;
|
||||
scanner->opt[option].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED;
|
||||
scanner->opt[option].unit = SANE_UNIT_NONE;
|
||||
scanner->opt[option].constraint_type = SANE_CONSTRAINT_RANGE;
|
||||
if (scanner->dev->model->asic_type == GENESYS_GL646)
|
||||
{
|
||||
if ((scanner->dev->model->flags & GENESYS_FLAG_14BIT_GAMMA) != 0)
|
||||
{
|
||||
scanner->opt[option].size = 16384 * sizeof (SANE_Word);
|
||||
scanner->opt[option].constraint.range = &u14_range;
|
||||
}
|
||||
else
|
||||
{ /* 12 bits gamma tables */
|
||||
scanner->opt[option].size = 4096 * sizeof (SANE_Word);
|
||||
scanner->opt[option].constraint.range = &u12_range;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* GL841 case */
|
||||
scanner->opt[option].size = 256 * sizeof (SANE_Word);
|
||||
scanner->opt[option].constraint.range = &u16_range;
|
||||
}
|
||||
/* default value is NULL */
|
||||
scanner->val[option].wa = NULL;
|
||||
}
|
||||
|
||||
static SANE_Status
|
||||
init_options (Genesys_Scanner * s)
|
||||
{
|
||||
|
@ -4629,7 +4694,7 @@ init_options (Genesys_Scanner * s)
|
|||
s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
|
||||
s->opt[OPT_MODE].size = max_string_size (mode_list);
|
||||
s->opt[OPT_MODE].constraint.string_list = mode_list;
|
||||
s->val[OPT_MODE].s = strdup ("Gray");
|
||||
s->val[OPT_MODE].s = strdup (SANE_VALUE_SCAN_MODE_GRAY);
|
||||
|
||||
/* scan source */
|
||||
s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
|
||||
|
@ -4735,6 +4800,56 @@ init_options (Genesys_Scanner * s)
|
|||
s->opt[OPT_BR_Y].constraint.range = &y_range;
|
||||
s->val[OPT_BR_Y].w = y_range.max;
|
||||
|
||||
/* "Enhancement" group: */
|
||||
s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement");
|
||||
s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
|
||||
s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
|
||||
s->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED;
|
||||
s->opt[OPT_ENHANCEMENT_GROUP].size = 0;
|
||||
s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
|
||||
|
||||
/* custom-gamma table */
|
||||
s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA;
|
||||
s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA;
|
||||
s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA;
|
||||
s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL;
|
||||
s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_ADVANCED;
|
||||
s->val[OPT_CUSTOM_GAMMA].b = SANE_FALSE;
|
||||
|
||||
/* grayscale gamma vector */
|
||||
s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR;
|
||||
s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR;
|
||||
s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR;
|
||||
init_gamma_vector_option (s, OPT_GAMMA_VECTOR);
|
||||
|
||||
/* red gamma vector */
|
||||
s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R;
|
||||
s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R;
|
||||
s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R;
|
||||
init_gamma_vector_option (s, OPT_GAMMA_VECTOR_R);
|
||||
|
||||
/* green gamma vector */
|
||||
s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G;
|
||||
s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G;
|
||||
s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G;
|
||||
init_gamma_vector_option (s, OPT_GAMMA_VECTOR_G);
|
||||
|
||||
/* blue gamma vector */
|
||||
s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B;
|
||||
s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B;
|
||||
s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B;
|
||||
init_gamma_vector_option (s, OPT_GAMMA_VECTOR_B);
|
||||
|
||||
/* currently, there are only gamma table options in this group,
|
||||
* so if the scanner doesn't support gamma table, disable the
|
||||
* whole group */
|
||||
if (!(s->dev->model->flags & GENESYS_FLAG_CUSTOM_GAMMA))
|
||||
{
|
||||
s->opt[OPT_ENHANCEMENT_GROUP].cap |= SANE_CAP_INACTIVE;
|
||||
s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE;
|
||||
DBG (DBG_info, "init_options: custom gamma disabled\n");
|
||||
}
|
||||
|
||||
/* "Extras" group: */
|
||||
s->opt[OPT_EXTRAS_GROUP].title = SANE_I18N ("Extras");
|
||||
s->opt[OPT_EXTRAS_GROUP].desc = "";
|
||||
|
@ -5033,15 +5148,8 @@ sane_exit (void)
|
|||
DBG (DBG_proc, "sane_exit: start\n");
|
||||
for (dev = first_dev; dev; dev = next)
|
||||
{
|
||||
if (dev->already_initialized)
|
||||
{
|
||||
if (dev->sensor.red_gamma_table)
|
||||
free (dev->sensor.red_gamma_table);
|
||||
if (dev->sensor.green_gamma_table)
|
||||
free (dev->sensor.green_gamma_table);
|
||||
if (dev->sensor.blue_gamma_table)
|
||||
free (dev->sensor.blue_gamma_table);
|
||||
}
|
||||
/* sane_close() free many fields, not much things left to
|
||||
* do here */
|
||||
next = dev->next;
|
||||
free (dev->file_name);
|
||||
free (dev);
|
||||
|
@ -5103,8 +5211,12 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle)
|
|||
|
||||
DBG (DBG_proc, "sane_open: start (devicename = `%s')\n", devicename);
|
||||
|
||||
if (devicename[0])
|
||||
/* devicename="" or devicename="genesys" are default values that use
|
||||
* first available device
|
||||
*/
|
||||
if (devicename[0] && strcmp ("genesys", devicename) != 0)
|
||||
{
|
||||
/* search for the given devicename in the device list */
|
||||
for (dev = first_dev; dev; dev = dev->next)
|
||||
if (strcmp (dev->file_name, devicename) == 0)
|
||||
break;
|
||||
|
@ -5122,7 +5234,7 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* empty devicename -> use first device */
|
||||
/* empty devicename or "genesys" -> use first device */
|
||||
dev = first_dev;
|
||||
if (dev)
|
||||
{
|
||||
|
@ -5219,16 +5331,19 @@ sane_close (SANE_Handle handle)
|
|||
sanei_genesys_buffer_free (&(s->dev->lines_buffer));
|
||||
sanei_genesys_buffer_free (&(s->dev->shrink_buffer));
|
||||
sanei_genesys_buffer_free (&(s->dev->out_buffer));
|
||||
FREE_IFNOT_NULL (s->dev->white_average_data);
|
||||
FREE_IFNOT_NULL (s->dev->dark_average_data);
|
||||
|
||||
if (s->dev->white_average_data != NULL)
|
||||
free (s->dev->white_average_data);
|
||||
if (s->dev->dark_average_data != NULL)
|
||||
free (s->dev->dark_average_data);
|
||||
/* free allocated gamma tables */
|
||||
FREE_IFNOT_NULL (s->dev->sensor.red_gamma_table);
|
||||
FREE_IFNOT_NULL (s->dev->sensor.green_gamma_table);
|
||||
FREE_IFNOT_NULL (s->dev->sensor.blue_gamma_table);
|
||||
|
||||
/* for an handful of bytes .. */
|
||||
free (s->opt[OPT_RESOLUTION].constraint.word_list);
|
||||
free (s->val[OPT_SOURCE].s);
|
||||
free (s->val[OPT_MODE].s);
|
||||
free (s->val[OPT_COLOR_FILTER].s);
|
||||
|
||||
if (prev)
|
||||
prev->next = s->next;
|
||||
|
@ -5255,12 +5370,291 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
|
|||
return s->opt + option;
|
||||
}
|
||||
|
||||
/* gets an option , called by sane_control_option */
|
||||
static SANE_Status
|
||||
get_option_value (Genesys_Scanner * s, int option, void *val)
|
||||
{
|
||||
unsigned int i;
|
||||
SANE_Word *table;
|
||||
u_int16_t *gamma;
|
||||
|
||||
switch (option)
|
||||
{
|
||||
/* word options: */
|
||||
case OPT_NUM_OPTS:
|
||||
case OPT_RESOLUTION:
|
||||
case OPT_BIT_DEPTH:
|
||||
case OPT_PREVIEW:
|
||||
case OPT_TL_X:
|
||||
case OPT_TL_Y:
|
||||
case OPT_BR_X:
|
||||
case OPT_BR_Y:
|
||||
case OPT_THRESHOLD:
|
||||
case OPT_DISABLE_INTERPOLATION:
|
||||
case OPT_LAMP_OFF_TIME:
|
||||
case OPT_CUSTOM_GAMMA:
|
||||
*(SANE_Word *) val = s->val[option].w;
|
||||
break;
|
||||
/* string options: */
|
||||
case OPT_MODE:
|
||||
case OPT_COLOR_FILTER:
|
||||
case OPT_SOURCE:
|
||||
strcpy (val, s->val[option].s);
|
||||
break;
|
||||
/* word array options */
|
||||
case OPT_GAMMA_VECTOR:
|
||||
table = (SANE_Word *) val;
|
||||
if (strcmp (s->val[OPT_COLOR_FILTER].s, "Red") == 0)
|
||||
{
|
||||
gamma = s->dev->sensor.red_gamma_table;
|
||||
}
|
||||
else if (strcmp (s->val[OPT_COLOR_FILTER].s, "Blue") == 0)
|
||||
{
|
||||
gamma = s->dev->sensor.blue_gamma_table;
|
||||
}
|
||||
else
|
||||
{
|
||||
gamma = s->dev->sensor.green_gamma_table;
|
||||
}
|
||||
for (i = 0; i < s->opt[option].size / sizeof (SANE_Word); i++)
|
||||
{
|
||||
table[i] = gamma[i];
|
||||
}
|
||||
break;
|
||||
case OPT_GAMMA_VECTOR_R:
|
||||
table = (SANE_Word *) val;
|
||||
for (i = 0; i < s->opt[option].size / sizeof (SANE_Word); i++)
|
||||
{
|
||||
table[i] = s->dev->sensor.red_gamma_table[i];
|
||||
}
|
||||
break;
|
||||
case OPT_GAMMA_VECTOR_G:
|
||||
table = (SANE_Word *) val;
|
||||
for (i = 0; i < s->opt[option].size / sizeof (SANE_Word); i++)
|
||||
{
|
||||
table[i] = s->dev->sensor.green_gamma_table[i];
|
||||
}
|
||||
break;
|
||||
case OPT_GAMMA_VECTOR_B:
|
||||
table = (SANE_Word *) val;
|
||||
for (i = 0; i < s->opt[option].size / sizeof (SANE_Word); i++)
|
||||
{
|
||||
table[i] = s->dev->sensor.blue_gamma_table[i];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DBG (DBG_warn, "get_option_value: can't get unknown option %d\n",
|
||||
option);
|
||||
}
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/* sets an option , called by sane_control_option */
|
||||
static SANE_Status
|
||||
set_option_value (Genesys_Scanner * s, int option, void *val,
|
||||
SANE_Int * myinfo)
|
||||
{
|
||||
SANE_Status status;
|
||||
SANE_Word *table;
|
||||
unsigned int i;
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case OPT_TL_X:
|
||||
case OPT_TL_Y:
|
||||
case OPT_BR_X:
|
||||
case OPT_BR_Y:
|
||||
s->val[option].w = *(SANE_Word *) val;
|
||||
RIE (calc_parameters (s));
|
||||
*myinfo |= SANE_INFO_RELOAD_PARAMS;
|
||||
break;
|
||||
case OPT_RESOLUTION:
|
||||
case OPT_BIT_DEPTH:
|
||||
case OPT_THRESHOLD:
|
||||
case OPT_DISABLE_INTERPOLATION:
|
||||
case OPT_PREVIEW:
|
||||
s->val[option].w = *(SANE_Word *) val;
|
||||
RIE (calc_parameters (s));
|
||||
*myinfo |= SANE_INFO_RELOAD_PARAMS;
|
||||
break;
|
||||
case OPT_SOURCE:
|
||||
if (strcmp (s->val[option].s, val) != 0)
|
||||
{ /* something changed */
|
||||
if (s->val[option].s)
|
||||
free (s->val[option].s);
|
||||
s->val[option].s = strdup (val);
|
||||
*myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
|
||||
}
|
||||
break;
|
||||
case OPT_MODE:
|
||||
if (s->val[option].s)
|
||||
free (s->val[option].s);
|
||||
s->val[option].s = strdup (val);
|
||||
if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_LINEART) == 0)
|
||||
{
|
||||
ENABLE (OPT_THRESHOLD);
|
||||
DISABLE (OPT_BIT_DEPTH);
|
||||
ENABLE (OPT_COLOR_FILTER);
|
||||
}
|
||||
else
|
||||
{
|
||||
DISABLE (OPT_THRESHOLD);
|
||||
if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_GRAY) == 0)
|
||||
{
|
||||
ENABLE (OPT_COLOR_FILTER);
|
||||
create_bpp_list (s, s->dev->model->bpp_gray_values);
|
||||
}
|
||||
else
|
||||
{
|
||||
DISABLE (OPT_COLOR_FILTER);
|
||||
create_bpp_list (s, s->dev->model->bpp_color_values);
|
||||
}
|
||||
if (s->bpp_list[0] < 2)
|
||||
DISABLE (OPT_BIT_DEPTH);
|
||||
else
|
||||
ENABLE (OPT_BIT_DEPTH);
|
||||
}
|
||||
RIE (calc_parameters (s));
|
||||
|
||||
/* if custom gamma, toggle gamma table options according to the mode */
|
||||
if (s->val[OPT_CUSTOM_GAMMA].b == SANE_TRUE)
|
||||
{
|
||||
if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_COLOR) == 0)
|
||||
{
|
||||
DISABLE (OPT_GAMMA_VECTOR);
|
||||
ENABLE (OPT_GAMMA_VECTOR_R);
|
||||
ENABLE (OPT_GAMMA_VECTOR_G);
|
||||
ENABLE (OPT_GAMMA_VECTOR_B);
|
||||
}
|
||||
else
|
||||
{
|
||||
ENABLE (OPT_GAMMA_VECTOR);
|
||||
DISABLE (OPT_GAMMA_VECTOR_R);
|
||||
DISABLE (OPT_GAMMA_VECTOR_G);
|
||||
DISABLE (OPT_GAMMA_VECTOR_B);
|
||||
}
|
||||
}
|
||||
|
||||
*myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
|
||||
break;
|
||||
case OPT_COLOR_FILTER:
|
||||
if (s->val[option].s)
|
||||
free (s->val[option].s);
|
||||
s->val[option].s = strdup (val);
|
||||
RIE (calc_parameters (s));
|
||||
break;
|
||||
case OPT_LAMP_OFF_TIME:
|
||||
if (*(SANE_Word *) val != s->val[option].w)
|
||||
{
|
||||
s->val[option].w = *(SANE_Word *) val;
|
||||
RIE (s->dev->model->cmd_set->
|
||||
set_powersaving (s->dev, s->val[option].w));
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_CUSTOM_GAMMA:
|
||||
*myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
|
||||
s->val[OPT_CUSTOM_GAMMA].b = *(SANE_Bool *) val;
|
||||
|
||||
if (s->val[OPT_CUSTOM_GAMMA].b == SANE_TRUE)
|
||||
{
|
||||
if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0)
|
||||
{
|
||||
DISABLE (OPT_GAMMA_VECTOR);
|
||||
ENABLE (OPT_GAMMA_VECTOR_R);
|
||||
ENABLE (OPT_GAMMA_VECTOR_G);
|
||||
ENABLE (OPT_GAMMA_VECTOR_B);
|
||||
}
|
||||
else
|
||||
{
|
||||
ENABLE (OPT_GAMMA_VECTOR);
|
||||
DISABLE (OPT_GAMMA_VECTOR_R);
|
||||
DISABLE (OPT_GAMMA_VECTOR_G);
|
||||
DISABLE (OPT_GAMMA_VECTOR_B);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DISABLE (OPT_GAMMA_VECTOR);
|
||||
DISABLE (OPT_GAMMA_VECTOR_R);
|
||||
DISABLE (OPT_GAMMA_VECTOR_G);
|
||||
DISABLE (OPT_GAMMA_VECTOR_B);
|
||||
/* restore default sensor gamma table */
|
||||
/* currently there is no sensor's specific gamma table,
|
||||
* tables are built by sanei_genesys_create_gamma_table */
|
||||
sanei_genesys_create_gamma_table (s->dev->sensor.red_gamma_table,
|
||||
s->opt[OPT_GAMMA_VECTOR_R].size /
|
||||
sizeof (SANE_Word),
|
||||
s->opt[OPT_GAMMA_VECTOR_R].
|
||||
constraint.range->max,
|
||||
s->opt[OPT_GAMMA_VECTOR_R].
|
||||
constraint.range->max,
|
||||
s->dev->sensor.red_gamma);
|
||||
sanei_genesys_create_gamma_table (s->dev->sensor.green_gamma_table,
|
||||
s->opt[OPT_GAMMA_VECTOR_G].size /
|
||||
sizeof (SANE_Word),
|
||||
s->opt[OPT_GAMMA_VECTOR_G].
|
||||
constraint.range->max,
|
||||
s->opt[OPT_GAMMA_VECTOR_G].
|
||||
constraint.range->max,
|
||||
s->dev->sensor.red_gamma);
|
||||
sanei_genesys_create_gamma_table (s->dev->sensor.blue_gamma_table,
|
||||
s->opt[OPT_GAMMA_VECTOR_B].size /
|
||||
sizeof (SANE_Word),
|
||||
s->opt[OPT_GAMMA_VECTOR_B].
|
||||
constraint.range->max,
|
||||
s->opt[OPT_GAMMA_VECTOR_B].
|
||||
constraint.range->max,
|
||||
s->dev->sensor.red_gamma);
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_GAMMA_VECTOR:
|
||||
table = (SANE_Word *) val;
|
||||
for (i = 0; i < s->opt[option].size / sizeof (SANE_Word); i++)
|
||||
{
|
||||
s->dev->sensor.red_gamma_table[i] = table[i];
|
||||
s->dev->sensor.green_gamma_table[i] = table[i];
|
||||
s->dev->sensor.blue_gamma_table[i] = table[i];
|
||||
}
|
||||
break;
|
||||
case OPT_GAMMA_VECTOR_R:
|
||||
table = (SANE_Word *) val;
|
||||
for (i = 0; i < s->opt[option].size / sizeof (SANE_Word); i++)
|
||||
{
|
||||
s->dev->sensor.red_gamma_table[i] = table[i];
|
||||
}
|
||||
break;
|
||||
case OPT_GAMMA_VECTOR_G:
|
||||
table = (SANE_Word *) val;
|
||||
for (i = 0; i < s->opt[option].size / sizeof (SANE_Word); i++)
|
||||
{
|
||||
s->dev->sensor.green_gamma_table[i] = table[i];
|
||||
}
|
||||
break;
|
||||
case OPT_GAMMA_VECTOR_B:
|
||||
table = (SANE_Word *) val;
|
||||
for (i = 0; i < s->opt[option].size / sizeof (SANE_Word); i++)
|
||||
{
|
||||
s->dev->sensor.blue_gamma_table[i] = table[i];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DBG (DBG_warn, "set_option_value: can't set unknown option %d\n",
|
||||
option);
|
||||
}
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
/* sets and gets scanner option values */
|
||||
SANE_Status
|
||||
sane_control_option (SANE_Handle handle, SANE_Int option,
|
||||
SANE_Action action, void *val, SANE_Int * info)
|
||||
{
|
||||
Genesys_Scanner *s = handle;
|
||||
SANE_Status status;
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
SANE_Word cap;
|
||||
SANE_Int myinfo = 0;
|
||||
|
||||
|
@ -5297,37 +5691,13 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
|
|||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
if (action == SANE_ACTION_GET_VALUE)
|
||||
{
|
||||
switch (option)
|
||||
{
|
||||
/* word options: */
|
||||
case OPT_NUM_OPTS:
|
||||
case OPT_RESOLUTION:
|
||||
case OPT_BIT_DEPTH:
|
||||
case OPT_PREVIEW:
|
||||
case OPT_TL_X:
|
||||
case OPT_TL_Y:
|
||||
case OPT_BR_X:
|
||||
case OPT_BR_Y:
|
||||
case OPT_THRESHOLD:
|
||||
case OPT_DISABLE_INTERPOLATION:
|
||||
case OPT_LAMP_OFF_TIME:
|
||||
*(SANE_Word *) val = s->val[option].w;
|
||||
break;
|
||||
/* string options: */
|
||||
case OPT_MODE:
|
||||
case OPT_COLOR_FILTER:
|
||||
case OPT_SOURCE:
|
||||
strcpy (val, s->val[option].s);
|
||||
break;
|
||||
default:
|
||||
DBG (DBG_warn, "sane_control_option: can't get unknown option %d\n",
|
||||
option);
|
||||
}
|
||||
}
|
||||
else if (action == SANE_ACTION_SET_VALUE)
|
||||
switch (action)
|
||||
{
|
||||
case SANE_ACTION_GET_VALUE:
|
||||
status = get_option_value (s, option, val);
|
||||
break;
|
||||
|
||||
case SANE_ACTION_SET_VALUE:
|
||||
if (!SANE_OPTION_IS_SETTABLE (cap))
|
||||
{
|
||||
DBG (DBG_warn, "sane_control_option: option %d is not settable\n",
|
||||
|
@ -5336,7 +5706,6 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
|
|||
}
|
||||
|
||||
status = sanei_constrain_value (s->opt + option, val, &myinfo);
|
||||
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_warn,
|
||||
|
@ -5345,113 +5714,31 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
|
|||
return status;
|
||||
}
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case OPT_TL_X:
|
||||
case OPT_TL_Y:
|
||||
case OPT_BR_X:
|
||||
case OPT_BR_Y:
|
||||
s->val[option].w = *(SANE_Word *) val;
|
||||
RIE (calc_parameters (s));
|
||||
myinfo |= SANE_INFO_RELOAD_PARAMS;
|
||||
break;
|
||||
case OPT_RESOLUTION:
|
||||
case OPT_BIT_DEPTH:
|
||||
case OPT_THRESHOLD:
|
||||
case OPT_DISABLE_INTERPOLATION:
|
||||
case OPT_PREVIEW:
|
||||
s->val[option].w = *(SANE_Word *) val;
|
||||
RIE (calc_parameters (s));
|
||||
myinfo |= SANE_INFO_RELOAD_PARAMS;
|
||||
break;
|
||||
case OPT_SOURCE:
|
||||
if (strcmp (s->val[option].s, val) != 0)
|
||||
{ /* something changed */
|
||||
if (s->val[option].s)
|
||||
free (s->val[option].s);
|
||||
s->val[option].s = strdup (val);
|
||||
if (strcmp (s->val[option].s, "Transparency Adapter") == 0)
|
||||
{
|
||||
/* RIE (gt68xx_device_lamp_control
|
||||
(s->dev, SANE_FALSE, SANE_TRUE));
|
||||
x_range.max = s->dev->model->x_size_ta;
|
||||
y_range.max = s->dev->model->y_size_ta; */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* RIE (gt68xx_device_lamp_control
|
||||
(s->dev, SANE_TRUE, SANE_FALSE));
|
||||
x_range.max = s->dev->model->x_size;
|
||||
y_range.max = s->dev->model->y_size; */
|
||||
}
|
||||
myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
|
||||
}
|
||||
break;
|
||||
case OPT_MODE:
|
||||
if (s->val[option].s)
|
||||
free (s->val[option].s);
|
||||
s->val[option].s = strdup (val);
|
||||
if (strcmp (s->val[option].s, "Lineart") == 0)
|
||||
{
|
||||
ENABLE (OPT_THRESHOLD);
|
||||
DISABLE (OPT_BIT_DEPTH);
|
||||
ENABLE (OPT_COLOR_FILTER);
|
||||
}
|
||||
else
|
||||
{
|
||||
DISABLE (OPT_THRESHOLD);
|
||||
if (strcmp (s->val[option].s, "Gray") == 0)
|
||||
{
|
||||
ENABLE (OPT_COLOR_FILTER);
|
||||
create_bpp_list (s, s->dev->model->bpp_gray_values);
|
||||
}
|
||||
else
|
||||
{
|
||||
DISABLE (OPT_COLOR_FILTER);
|
||||
create_bpp_list (s, s->dev->model->bpp_color_values);
|
||||
}
|
||||
if (s->bpp_list[0] < 2)
|
||||
DISABLE (OPT_BIT_DEPTH);
|
||||
else
|
||||
ENABLE (OPT_BIT_DEPTH);
|
||||
}
|
||||
RIE (calc_parameters (s));
|
||||
myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
|
||||
break;
|
||||
case OPT_COLOR_FILTER:
|
||||
if (s->val[option].s)
|
||||
free (s->val[option].s);
|
||||
s->val[option].s = strdup (val);
|
||||
RIE (calc_parameters (s));
|
||||
break;
|
||||
case OPT_LAMP_OFF_TIME:
|
||||
if (*(SANE_Word *) val != s->val[option].w)
|
||||
{
|
||||
s->val[option].w = *(SANE_Word *) val;
|
||||
RIE (s->dev->model->cmd_set->
|
||||
set_powersaving (s->dev, s->val[option].w));
|
||||
}
|
||||
break;
|
||||
/* string options: */
|
||||
status = set_option_value (s, option, val, &myinfo);
|
||||
break;
|
||||
|
||||
default:
|
||||
DBG (DBG_warn, "sane_control_option: can't set unknown option %d\n",
|
||||
option);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
case SANE_ACTION_SET_AUTO:
|
||||
DBG (DBG_error,
|
||||
"sane_control_option: SANE_ACTION_SET_AUTO unsupported since no option has SANE_CAP_AUTOMATIC\n");
|
||||
status = SANE_STATUS_INVAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
DBG (DBG_warn, "sane_control_option: unknown action %d for option %d\n",
|
||||
action, option);
|
||||
return SANE_STATUS_INVAL;
|
||||
status = SANE_STATUS_INVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (info)
|
||||
*info = myinfo;
|
||||
|
||||
DBG (DBG_io2, "sane_control_option: exit\n");
|
||||
return SANE_STATUS_GOOD;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
SANE_Status
|
||||
sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
|
||||
{
|
||||
|
|
|
@ -81,6 +81,14 @@ enum Genesys_Option
|
|||
OPT_BR_X, /* bottom-right x */
|
||||
OPT_BR_Y, /* bottom-right y */
|
||||
|
||||
/* advanced image enhancement options */
|
||||
OPT_ENHANCEMENT_GROUP,
|
||||
OPT_CUSTOM_GAMMA, /* toggle to enable custom gamma tables */
|
||||
OPT_GAMMA_VECTOR,
|
||||
OPT_GAMMA_VECTOR_R,
|
||||
OPT_GAMMA_VECTOR_G,
|
||||
OPT_GAMMA_VECTOR_B,
|
||||
|
||||
OPT_EXTRAS_GROUP,
|
||||
OPT_LAMP_OFF_TIME,
|
||||
OPT_THRESHOLD,
|
||||
|
|
|
@ -561,7 +561,9 @@ static Genesys_Model hp2300c_model = {
|
|||
| GENESYS_FLAG_14BIT_GAMMA
|
||||
| GENESYS_FLAG_SEARCH_START
|
||||
| GENESYS_FLAG_MUST_WAIT
|
||||
| GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION,
|
||||
| GENESYS_FLAG_DARK_CALIBRATION
|
||||
| GENESYS_FLAG_OFFSET_CALIBRATION
|
||||
| GENESYS_FLAG_CUSTOM_GAMMA,
|
||||
9,
|
||||
132
|
||||
};
|
||||
|
@ -607,7 +609,9 @@ static Genesys_Model hp2400c_model = {
|
|||
| GENESYS_FLAG_14BIT_GAMMA
|
||||
| GENESYS_FLAG_SEARCH_START
|
||||
| GENESYS_FLAG_MUST_WAIT
|
||||
| GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION,
|
||||
| GENESYS_FLAG_DARK_CALIBRATION
|
||||
| GENESYS_FLAG_OFFSET_CALIBRATION
|
||||
| GENESYS_FLAG_CUSTOM_GAMMA,
|
||||
20,
|
||||
132
|
||||
};
|
||||
|
@ -783,7 +787,9 @@ static Genesys_Model medion_md5345_model = {
|
|||
| GENESYS_FLAG_SKIP_WARMUP
|
||||
| GENESYS_FLAG_SEARCH_START
|
||||
| GENESYS_FLAG_DARK_CALIBRATION
|
||||
| GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_OFFSET_CALIBRATION,
|
||||
| GENESYS_FLAG_STAGGERED_LINE
|
||||
| GENESYS_FLAG_OFFSET_CALIBRATION
|
||||
| GENESYS_FLAG_CUSTOM_GAMMA,
|
||||
32,
|
||||
200
|
||||
};
|
||||
|
|
|
@ -269,7 +269,7 @@ gl646_bulk_write_register (Genesys_Device * dev,
|
|||
elems = i;
|
||||
size = i * 2;
|
||||
|
||||
DBG (DBG_io, "gl646_bulk_write_register (elems= %lu, size = %lu)\n",
|
||||
DBG (DBG_io, "gl646_bulk_write_register (elems= %lu, size = %lu)\n",
|
||||
(u_long) elems, (u_long) size);
|
||||
|
||||
|
||||
|
@ -312,7 +312,7 @@ gl646_bulk_write_register (Genesys_Device * dev,
|
|||
for (i = 0; i < size; i += 2)
|
||||
DBG (DBG_io2, "reg[0x%02x] = 0x%02x\n", buffer[i], buffer[i + 1]);
|
||||
|
||||
DBG (DBG_io, "gl646_bulk_write_register: wrote %lu bytes, %lu registers\n",
|
||||
DBG (DBG_io, "gl646_bulk_write_register: wrote %lu bytes, %lu registers\n",
|
||||
(u_long) size, (u_long) elems);
|
||||
return status;
|
||||
}
|
||||
|
@ -1322,7 +1322,7 @@ gl646_set_motor_power (Genesys_Register_Set * regs, SANE_Bool set)
|
|||
}
|
||||
|
||||
static void
|
||||
gl646_set_lamp_power (Genesys_Device * dev,
|
||||
gl646_set_lamp_power (Genesys_Device * dev,
|
||||
Genesys_Register_Set * regs, SANE_Bool set)
|
||||
{
|
||||
if (set)
|
||||
|
@ -1430,8 +1430,9 @@ gl646_set_powersaving (Genesys_Device * dev, int delay /* in minutes */ )
|
|||
local_reg[3].value = exposure_time / 256; /* highbyte */
|
||||
local_reg[4].value = exposure_time & 255; /* lowbyte */
|
||||
|
||||
status = gl646_bulk_write_register (dev, local_reg,
|
||||
sizeof (local_reg)/sizeof (local_reg[0]));
|
||||
status = gl646_bulk_write_register (dev, local_reg,
|
||||
sizeof (local_reg) /
|
||||
sizeof (local_reg[0]));
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
DBG (DBG_error,
|
||||
"gl646_set_powersaving: Failed to bulk write registers: %s\n",
|
||||
|
@ -1464,8 +1465,9 @@ gl646_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg,
|
|||
else
|
||||
local_reg[2].value = 0x00; /* do not start motor yet */
|
||||
|
||||
status = gl646_bulk_write_register (dev, local_reg,
|
||||
sizeof (local_reg)/sizeof (local_reg[0]));
|
||||
status = gl646_bulk_write_register (dev, local_reg,
|
||||
sizeof (local_reg) /
|
||||
sizeof (local_reg[0]));
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
|
@ -1576,7 +1578,8 @@ gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home)
|
|||
usleep (200000UL);
|
||||
}
|
||||
|
||||
memcpy (local_reg, dev->reg, (GENESYS_GL646_MAX_REGS + 1) * sizeof(Genesys_Register_Set));
|
||||
memcpy (local_reg, dev->reg,
|
||||
(GENESYS_GL646_MAX_REGS + 1) * sizeof (Genesys_Register_Set));
|
||||
|
||||
prepare_steps = 4;
|
||||
exposure_time = 6 * MOTOR_SPEED_MAX;
|
||||
|
@ -1629,9 +1632,7 @@ gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home)
|
|||
}
|
||||
else
|
||||
{
|
||||
sanei_genesys_create_slope_table (dev, slope_table0, prepare_steps, 0,
|
||||
exposure_time, 0,
|
||||
dev->motor.base_ydpi, /*MOTOR_GEAR */
|
||||
sanei_genesys_create_slope_table (dev, slope_table0, prepare_steps, 0, exposure_time, 0, dev->motor.base_ydpi, /*MOTOR_GEAR */
|
||||
0);
|
||||
}
|
||||
|
||||
|
@ -1682,8 +1683,7 @@ gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home)
|
|||
return status;
|
||||
}
|
||||
|
||||
status =
|
||||
gl646_bulk_write_register (dev, local_reg, GENESYS_GL646_MAX_REGS);
|
||||
status = gl646_bulk_write_register (dev, local_reg, GENESYS_GL646_MAX_REGS);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
|
@ -1934,7 +1934,8 @@ gl646_search_start_position (Genesys_Device * dev)
|
|||
|
||||
DBG (DBG_proc, "gl646_search_start_position\n");
|
||||
memset (local_reg, 0, sizeof (local_reg));
|
||||
memcpy (local_reg, dev->reg, (GENESYS_GL646_MAX_REGS + 1) * sizeof(Genesys_Register_Set));
|
||||
memcpy (local_reg, dev->reg,
|
||||
(GENESYS_GL646_MAX_REGS + 1) * sizeof (Genesys_Register_Set));
|
||||
|
||||
gettimeofday (&tv, NULL);
|
||||
/* is scanner warm enough ? */
|
||||
|
@ -2064,8 +2065,7 @@ gl646_search_start_position (Genesys_Device * dev)
|
|||
}
|
||||
|
||||
/* send to scanner */
|
||||
status =
|
||||
gl646_bulk_write_register (dev, local_reg, GENESYS_GL646_MAX_REGS);
|
||||
status = gl646_bulk_write_register (dev, local_reg, GENESYS_GL646_MAX_REGS);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
|
@ -2184,7 +2184,8 @@ gl646_search_start_position (Genesys_Device * dev)
|
|||
/* update regs to copy ASIC internal state */
|
||||
dev->reg[reg_0x01].value = local_reg[reg_0x01].value;
|
||||
dev->reg[reg_0x02].value = local_reg[reg_0x02].value;
|
||||
memcpy (dev->reg, local_reg, (GENESYS_GL646_MAX_REGS + 1) * sizeof(Genesys_Register_Set));
|
||||
memcpy (dev->reg, local_reg,
|
||||
(GENESYS_GL646_MAX_REGS + 1) * sizeof (Genesys_Register_Set));
|
||||
|
||||
status =
|
||||
sanei_genesys_search_reference_point (dev, data, start_pixel, dpi, pixels,
|
||||
|
@ -2307,14 +2308,8 @@ gl646_init_regs_for_coarse_calibration (Genesys_Device * dev)
|
|||
|
||||
/* todo: only 2 steps? */
|
||||
|
||||
steps_sum =
|
||||
sanei_genesys_create_slope_table (dev, slope_table,
|
||||
dev->calib_reg[reg_0x21].value,
|
||||
dev->calib_reg[reg_0x02].
|
||||
value & REG02_STEPSEL,
|
||||
dev->settings.exposure_time, 0,
|
||||
dev->motor.base_ydpi, /*MOTOR_GEAR */
|
||||
0);
|
||||
steps_sum = sanei_genesys_create_slope_table (dev, slope_table, dev->calib_reg[reg_0x21].value, dev->calib_reg[reg_0x02].value & REG02_STEPSEL, dev->settings.exposure_time, 0, dev->motor.base_ydpi, /*MOTOR_GEAR */
|
||||
0);
|
||||
|
||||
/* todo: z1 = z2 = 0? */
|
||||
sanei_genesys_calculate_zmode (dev,
|
||||
|
@ -2353,8 +2348,7 @@ gl646_init_regs_for_coarse_calibration (Genesys_Device * dev)
|
|||
}
|
||||
|
||||
status =
|
||||
gl646_bulk_write_register (dev, dev->calib_reg,
|
||||
GENESYS_GL646_MAX_REGS);
|
||||
gl646_bulk_write_register (dev, dev->calib_reg, GENESYS_GL646_MAX_REGS);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
|
@ -2400,7 +2394,25 @@ gl646_init_regs_for_shading (Genesys_Device * dev)
|
|||
/* monochrome / color scan */
|
||||
dev->calib_reg[reg_0x04].value &= ~REG04_FILTER;
|
||||
if (channels == 1)
|
||||
dev->calib_reg[reg_0x04].value |= 0x08;
|
||||
{
|
||||
switch (dev->settings.color_filter)
|
||||
{
|
||||
/* red */
|
||||
case 0:
|
||||
dev->calib_reg[reg_0x04].value |= 0x04;
|
||||
break;
|
||||
/* green */
|
||||
case 1:
|
||||
dev->calib_reg[reg_0x04].value |= 0x08;
|
||||
break;
|
||||
/* blue */
|
||||
case 2:
|
||||
dev->calib_reg[reg_0x04].value |= 0x0c;
|
||||
break;
|
||||
default:
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* disable forward/backward+motor, stepsel = 1 */
|
||||
dev->calib_reg[reg_0x02].value =
|
||||
|
@ -2638,8 +2650,7 @@ gl646_init_regs_for_shading (Genesys_Device * dev)
|
|||
}
|
||||
|
||||
status =
|
||||
gl646_bulk_write_register (dev, dev->calib_reg,
|
||||
GENESYS_GL646_MAX_REGS);
|
||||
gl646_bulk_write_register (dev, dev->calib_reg, GENESYS_GL646_MAX_REGS);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
|
@ -2821,15 +2832,34 @@ gl646_init_regs_for_scan (Genesys_Device * dev)
|
|||
|
||||
/* monochrome / color scan */
|
||||
dev->reg[reg_0x04].value &= ~(REG04_FILTER | REG04_BITSET);
|
||||
/* we could make the color filter used an advanced option of the backend */
|
||||
|
||||
/* select color filter based on settings */
|
||||
if (channels == 1)
|
||||
dev->reg[reg_0x04].value |= 0x08; /* green filter */
|
||||
{
|
||||
switch (dev->settings.color_filter)
|
||||
{
|
||||
/* red */
|
||||
case 0:
|
||||
dev->reg[reg_0x04].value |= 0x04;
|
||||
break;
|
||||
/* green */
|
||||
case 1:
|
||||
dev->reg[reg_0x04].value |= 0x08;
|
||||
break;
|
||||
/* blue */
|
||||
case 2:
|
||||
dev->reg[reg_0x04].value |= 0x0c;
|
||||
break;
|
||||
default:
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* bit depth: 8bit + gamma, 16 bits + no gamma */
|
||||
if (dev->settings.scan_mode == 0)
|
||||
{
|
||||
/* lineart, todo : find logs of real lineart, not an emulated one
|
||||
with gray level scanning */
|
||||
/* lineart, TODO : find logs of real lineart, not an emulated one
|
||||
with gray level scanning, since can't make it work on doc basis */
|
||||
depth = 8;
|
||||
dev->reg[reg_0x04].value &= ~REG04_LINEART;
|
||||
}
|
||||
|
@ -3198,22 +3228,6 @@ gl646_send_gamma_table (Genesys_Device * dev, SANE_Bool generic)
|
|||
else
|
||||
size = 4096;
|
||||
|
||||
/* table address */
|
||||
switch (dev->reg[reg_0x05].value >> 6)
|
||||
{
|
||||
case 0: /* 600 dpi */
|
||||
address = 0x09000;
|
||||
break;
|
||||
case 1: /* 1200 dpi */
|
||||
address = 0x11000;
|
||||
break;
|
||||
case 2: /* 2400 dpi */
|
||||
address = 0x20000;
|
||||
break;
|
||||
default:
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
/* allocate temporary gamma tables: 16 bits words, 3 channels */
|
||||
gamma = (u_int8_t *) malloc (size * 2 * 3);
|
||||
if (!gamma)
|
||||
|
@ -3246,6 +3260,23 @@ gl646_send_gamma_table (Genesys_Device * dev, SANE_Bool generic)
|
|||
}
|
||||
}
|
||||
|
||||
/* table address */
|
||||
switch (dev->reg[reg_0x05].value >> 6)
|
||||
{
|
||||
case 0: /* 600 dpi */
|
||||
address = 0x09000;
|
||||
break;
|
||||
case 1: /* 1200 dpi */
|
||||
address = 0x11000;
|
||||
break;
|
||||
case 2: /* 2400 dpi */
|
||||
address = 0x20000;
|
||||
break;
|
||||
default:
|
||||
free (gamma);
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
/* send address */
|
||||
status = sanei_genesys_set_buffer_address (dev, address);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
|
@ -3371,7 +3402,25 @@ gl646_offset_calibration (Genesys_Device * dev)
|
|||
(dev->calib_reg[reg_0x04].
|
||||
value & ~REG04_LINEART & ~REG04_FILTER) | REG04_BITSET;
|
||||
if (channels == 1)
|
||||
dev->calib_reg[reg_0x04].value |= 0x08; /* green filter */
|
||||
{
|
||||
switch (dev->settings.color_filter)
|
||||
{
|
||||
/* red */
|
||||
case 0:
|
||||
dev->calib_reg[reg_0x04].value |= 0x04;
|
||||
break;
|
||||
/* green */
|
||||
case 1:
|
||||
dev->calib_reg[reg_0x04].value |= 0x08;
|
||||
break;
|
||||
/* blue */
|
||||
case 2:
|
||||
dev->calib_reg[reg_0x04].value |= 0x0c;
|
||||
break;
|
||||
default:
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
}
|
||||
|
||||
dev->calib_reg[reg_0x05].value = (dev->calib_reg[reg_0x05].value & ~REG05_GMMENB); /* disable gamma */
|
||||
|
||||
|
@ -3855,7 +3904,8 @@ gl646_init_regs_for_warmup (Genesys_Device * dev,
|
|||
|
||||
DBG (DBG_proc, "gl646_warmup_lamp\n");
|
||||
|
||||
memcpy (local_reg, dev->reg, (GENESYS_GL646_MAX_REGS + 1) * sizeof(Genesys_Register_Set));
|
||||
memcpy (local_reg, dev->reg,
|
||||
(GENESYS_GL646_MAX_REGS + 1) * sizeof (Genesys_Register_Set));
|
||||
*total_size = num_pixels * 3 * 2 * 1; /* colors * bytes_per_color * scan lines */
|
||||
|
||||
/* ST12: 0x01 0x00 0x02 0x41 0x03 0x1f 0x04 0x53 0x05 0x10 0x06 0x10 0x08 0x02 0x09 0x00 0x0a 0x06 0x0b 0x04 */
|
||||
|
@ -4019,8 +4069,7 @@ gl646_init_regs_for_warmup (Genesys_Device * dev,
|
|||
|
||||
RIE (gl646_set_fe (dev, AFE_INIT));
|
||||
|
||||
RIE (gl646_bulk_write_register
|
||||
(dev, local_reg, GENESYS_GL646_MAX_REGS));
|
||||
RIE (gl646_bulk_write_register (dev, local_reg, GENESYS_GL646_MAX_REGS));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -4046,7 +4095,8 @@ gl646_repark_head (Genesys_Device * dev)
|
|||
DBG (DBG_proc, "gl646_repark_head\n");
|
||||
|
||||
memset (local_reg, 0, sizeof (local_reg));
|
||||
memcpy (local_reg, dev->reg, (GENESYS_GL646_MAX_REGS + 1) * sizeof(Genesys_Register_Set));
|
||||
memcpy (local_reg, dev->reg,
|
||||
(GENESYS_GL646_MAX_REGS + 1) * sizeof (Genesys_Register_Set));
|
||||
|
||||
local_reg[reg_0x01].value =
|
||||
local_reg[reg_0x01].value & ~REG01_DVDSET & ~REG01_FASTMOD & ~REG01_SCAN;
|
||||
|
@ -4156,8 +4206,7 @@ gl646_repark_head (Genesys_Device * dev)
|
|||
return status;
|
||||
}
|
||||
|
||||
status =
|
||||
gl646_bulk_write_register (dev, local_reg, GENESYS_GL646_MAX_REGS);
|
||||
status = gl646_bulk_write_register (dev, local_reg, GENESYS_GL646_MAX_REGS);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error, "gl646_repark_head: failed to send registers: %s\n",
|
||||
|
@ -4227,7 +4276,7 @@ gl646_init (Genesys_Device * dev)
|
|||
dev->dark_average_data = NULL;
|
||||
dev->white_average_data = NULL;
|
||||
|
||||
dev->settings.color_filter = 0;
|
||||
dev->settings.color_filter = 1; /* green filter by default */
|
||||
gettimeofday (&tv, NULL);
|
||||
dev->init_date = tv.tv_sec;
|
||||
|
||||
|
@ -4275,7 +4324,7 @@ gl646_init (Genesys_Device * dev)
|
|||
dev->reg[reg_0x21].value,
|
||||
dev->reg[reg_0x02].
|
||||
value & REG02_STEPSEL,
|
||||
dev->settings.exposure_time, 0, 600,
|
||||
dev->settings.exposure_time, 0, 600,
|
||||
0);
|
||||
sanei_genesys_create_slope_table (dev, dev->slope_table1,
|
||||
dev->reg[reg_0x6b].value,
|
||||
|
@ -4288,7 +4337,8 @@ gl646_init (Genesys_Device * dev)
|
|||
sanei_genesys_create_slope_table (dev, dev->slope_table0,
|
||||
dev->reg[reg_0x21].value,
|
||||
dev->reg[reg_0x02].
|
||||
value & REG02_STEPSEL, 250, 0, 600, 0);
|
||||
value & REG02_STEPSEL, 250, 0, 600,
|
||||
0);
|
||||
sanei_genesys_create_slope_table (dev, dev->slope_table1,
|
||||
dev->reg[reg_0x6b].value,
|
||||
(dev->reg[reg_0x6a].
|
||||
|
@ -4366,16 +4416,17 @@ gl646_init (Genesys_Device * dev)
|
|||
/* fix for timeouts at init */
|
||||
if (dev->model->ccd_type == CCD_5345)
|
||||
{
|
||||
sanei_usb_set_timeout (2 * 1000);
|
||||
/* we read data without any pending scan to trigger timeout */
|
||||
status = dev->model->cmd_set->bulk_read_data (dev, 0x45, data, 64);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
/* expected error */
|
||||
DBG (DBG_error, "gl646_init: read stream reset ... %s\n",
|
||||
DBG (DBG_info, "gl646_init: read stream reset ... %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
/* restore timeout */
|
||||
sanei_usb_set_timeout (30 * 1000);
|
||||
}
|
||||
|
||||
/* Move home */
|
||||
|
@ -4412,7 +4463,8 @@ gl646_init (Genesys_Device * dev)
|
|||
}
|
||||
|
||||
/* initial calibration reg values */
|
||||
memcpy (dev->calib_reg, dev->reg, (GENESYS_GL646_MAX_REGS + 1) * sizeof(Genesys_Register_Set));
|
||||
memcpy (dev->calib_reg, dev->reg,
|
||||
(GENESYS_GL646_MAX_REGS + 1) * sizeof (Genesys_Register_Set));
|
||||
|
||||
/* Set powersaving (default = 15 minutes) */
|
||||
RIE (gl646_set_powersaving (dev, 15));
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
creation function */
|
||||
|
||||
#define GENESYS_FLAG_DARK_WHITE_CALIBRATION (1 << 12) /*yet another calibration method. does white and dark shading in one run, depending on a black and a white strip*/
|
||||
#define GENESYS_FLAG_CUSTOM_GAMMA (1 << 13) /* allow custom gamma tables */
|
||||
|
||||
/* USB control message values */
|
||||
#define REQUEST_TYPE_IN (USB_TYPE_VENDOR | USB_DIR_IN)
|
||||
|
|
Ładowanie…
Reference in New Issue