From 79fbd0c2f173ffb9f476f227ec77f052b34bfabc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Voltz?= Date: Sat, 5 Apr 2008 09:21:56 +0000 Subject: [PATCH] - 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 readable --- ChangeLog | 8 + backend/genesys.c | 637 +++++++++++++++++++++++++++----------- backend/genesys.h | 8 + backend/genesys_devices.c | 12 +- backend/genesys_gl646.c | 178 +++++++---- backend/genesys_low.h | 1 + 6 files changed, 603 insertions(+), 241 deletions(-) diff --git a/ChangeLog b/ChangeLog index 92292e8de..371489196 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-04-05 Stéphane Voltz + * 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 * backend/rts8891.c: split sane_control_option() to make it more readable diff --git a/backend/genesys.c b/backend/genesys.c index 4fdb6b05c..084edbcfa 100644 --- a/backend/genesys.c +++ b/backend/genesys.c @@ -2,7 +2,7 @@ Copyright (C) 2003, 2004 Henning Meier-Geinitz Copyright (C) 2004, 2005 Gerhard Jaeger - Copyright (C) 2004, 2007 Stephane Voltz + Copyright (C) 2004, 2008 Stéphane Voltz Copyright (C) 2005, 2006 Pierre Willenbrock Copyright (C) 2006 Laurent Charpentier Copyright (C) 2007 Luke @@ -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) { diff --git a/backend/genesys.h b/backend/genesys.h index 3ed7762c2..01e178e86 100644 --- a/backend/genesys.h +++ b/backend/genesys.h @@ -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, diff --git a/backend/genesys_devices.c b/backend/genesys_devices.c index 832e5de58..6baba6195 100644 --- a/backend/genesys_devices.c +++ b/backend/genesys_devices.c @@ -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 }; diff --git a/backend/genesys_gl646.c b/backend/genesys_gl646.c index fe46bf011..4b82458c1 100644 --- a/backend/genesys_gl646.c +++ b/backend/genesys_gl646.c @@ -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)); diff --git a/backend/genesys_low.h b/backend/genesys_low.h index cb11793a2..8ce295e88 100644 --- a/backend/genesys_low.h +++ b/backend/genesys_low.h @@ -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)