From 351b7328520c16730ceb46e5acae16038c42185e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Tue, 16 Feb 2021 18:24:19 +0100 Subject: New upstream version 1.0.32 --- backend/escl/escl.c | 587 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 550 insertions(+), 37 deletions(-) (limited to 'backend/escl/escl.c') diff --git a/backend/escl/escl.c b/backend/escl/escl.c index c40fd98..bb62219 100644 --- a/backend/escl/escl.c +++ b/backend/escl/escl.c @@ -16,8 +16,8 @@ for more details. You should have received a copy of the GNU General Public License - along with sane; see the file COPYING. If not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with sane; see the file COPYING. + If not, see . This file implements a SANE backend for eSCL scanners. */ @@ -29,15 +29,32 @@ #include -#include - #include "../include/sane/saneopts.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" + +#ifndef SANE_NAME_SHARPEN +# define SANE_NAME_SHARPEN "sharpen" +# define SANE_TITLE_SHARPEN SANE_I18N("Sharpen") +# define SANE_DESC_SHARPEN SANE_I18N("Set sharpen value.") +#endif + +#ifndef SANE_NAME_THRESHOLD +# define SANE_NAME_THRESHOLD "threshold" +#endif +#ifndef SANE_TITLE_THRESHOLD +# define SANE_TITLE_THRESHOLD SANE_I18N("Threshold") +#endif +#ifndef SANE_DESC_THRESHOLD +# define SANE_DESC_THRESHOLD \ + SANE_I18N("Set threshold for line-art scans.") +#endif + #define min(A,B) (((A)<(B)) ? (A) : (B)) #define max(A,B) (((A)>(B)) ? (A) : (B)) +#define IS_ACTIVE(OPTION) (((handler->opt[OPTION].cap) & SANE_CAP_INACTIVE) == 0) #define INPUT_BUFFER_SIZE 4096 static const SANE_Device **devlist = NULL; @@ -56,6 +73,10 @@ typedef struct Handled { SANE_Range x_range2; SANE_Range y_range1; SANE_Range y_range2; + SANE_Range brightness_range; + SANE_Range contrast_range; + SANE_Range sharpen_range; + SANE_Range thresold_range; SANE_Bool cancel; SANE_Bool write_scan_data; SANE_Bool decompress_scan_data; @@ -70,7 +91,10 @@ escl_free_device(ESCL_Device *current) free((void*)current->ip_address); free((void*)current->model_name); free((void*)current->type); - free(current->unix_socket); + free((void*)current->is); + free((void*)current->uuid); + free((void*)current->unix_socket); + curl_slist_free_all(current->hack); free(current); return NULL; } @@ -110,6 +134,10 @@ escl_check_and_add_device(ESCL_Device *current) DBG (10, "Scanner Type allocation failure.\n"); return (SANE_STATUS_NO_MEM); } + if (!current->is) { + DBG (10, "Scanner Is allocation failure.\n"); + return (SANE_STATUS_NO_MEM); + } ++num_devices; current->next = list_devices_primary; list_devices_primary = current; @@ -150,14 +178,20 @@ escl_add_in_list(ESCL_Device *current) * \return escl_add_in_list(current) */ SANE_Status -escl_device_add(int port_nb, const char *model_name, char *ip_address, char *type) +escl_device_add(int port_nb, + const char *model_name, + char *ip_address, + const char *is, + const char *uuid, + char *type) { char tmp[PATH_MAX] = { 0 }; char *model = NULL; ESCL_Device *current = NULL; DBG (10, "escl_device_add\n"); for (current = list_devices_primary; current; current = current->next) { - if (strcmp(current->ip_address, ip_address) == 0) + if ((strcmp(current->ip_address, ip_address) == 0) || + (uuid && current->uuid && !strcmp(current->uuid, uuid))) { if (strcmp(current->type, type)) { @@ -166,6 +200,10 @@ escl_device_add(int port_nb, const char *model_name, char *ip_address, char *typ { free (current->type); current->type = strdup(type); + if (strcmp(current->ip_address, ip_address)) { + free (current->ip_address); + current->ip_address = strdup(ip_address); + } current->port_nb = port_nb; current->https = SANE_TRUE; } @@ -191,7 +229,12 @@ escl_device_add(int port_nb, const char *model_name, char *ip_address, char *typ model = (char*)(tmp[0] != 0 ? tmp : model_name); current->model_name = strdup(model); current->ip_address = strdup(ip_address); + memset(tmp, 0, PATH_MAX); + snprintf(tmp, sizeof(tmp), "%s scanner", (is ? is : "flatbed or ADF")); + current->is = strdup(tmp); current->type = strdup(type); + if (uuid) + current->uuid = strdup(uuid); return escl_add_in_list(current); } @@ -259,7 +302,7 @@ get_vendor(char *search) * \brief Function that checks if the url of the received scanner is secured or not (http / https). * --> if the url is not secured, our own url will be composed like "http://'ip':'port'". * --> else, our own url will be composed like "https://'ip':'port'". - * AND, it's in this function that we gather all the informations of the url (that were in our list) : + * AND, it's in this function that we gather all the information of the url (that were in our list) : * the model_name, the port, the ip, and the type of url. * SO, leaving this function, we have in memory the complete url. * @@ -308,7 +351,7 @@ convertFromESCLDev(ESCL_Device *cdev) DBG (10, "Model allocation failure.\n"); goto freename; } - sdev->type = strdup("flatbed scanner"); + sdev->type = strdup(cdev->is); if (!sdev->type) { DBG (10, "Scanner Type allocation failure.\n"); goto freevendor; @@ -383,7 +426,8 @@ sane_exit(void) * \return escl_add_in_list(escl_device) if the parsing worked, SANE_STATUS_GOOD otherwise. */ static SANE_Status -attach_one_config(SANEI_Config __sane_unused__ *config, const char *line) +attach_one_config(SANEI_Config __sane_unused__ *config, const char *line, + void __sane_unused__ *data) { int port = 0; SANE_Status status; @@ -392,6 +436,7 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line) if (strncmp(line, "device", 6) == 0) { char *name_str = NULL; char *opt_model = NULL; + char *opt_hack = NULL; line = sanei_config_get_string(line + 6, &name_str); DBG (10, "New Escl_Device URL [%s].\n", (name_str ? name_str : "VIDE")); @@ -403,6 +448,10 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line) line = sanei_config_get_string(line, &opt_model); DBG (10, "New Escl_Device model [%s].\n", opt_model); } + if (*line) { + line = sanei_config_get_string(line, &opt_hack); + DBG (10, "New Escl_Device hack [%s].\n", opt_hack); + } escl_free_device(escl_device); escl_device = (ESCL_Device*)calloc(1, sizeof(ESCL_Device)); @@ -419,7 +468,9 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line) return status; } escl_device->model_name = opt_model ? opt_model : strdup("Unknown model"); - escl_device->type = strdup("flatbed scanner"); + escl_device->is = strdup("flatbed or ADF scanner"); + escl_device->type = strdup("In url"); + escl_device->uuid = NULL; } if (strncmp(line, "[device]", 8) == 0) { @@ -430,7 +481,7 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line) return (SANE_STATUS_NO_MEM); } } - if (strncmp(line, "ip", 2) == 0) { + else if (strncmp(line, "ip", 2) == 0) { const char *ip_space = sanei_config_skip_whitespace(line + 2); DBG (10, "New Escl_Device IP [%s].", (ip_space ? ip_space : "VIDE")); if (escl_device != NULL && ip_space != NULL) { @@ -438,14 +489,14 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line) escl_device->ip_address = strdup(ip_space); } } - if (sscanf(line, "port %i", &port) == 1 && port != 0) { + else if (sscanf(line, "port %i", &port) == 1 && port != 0) { DBG (10, "New Escl_Device PORT [%d].", port); if (escl_device != NULL) { DBG (10, "New Escl_Device PORT Affected."); escl_device->port_nb = port; } } - if (strncmp(line, "model", 5) == 0) { + else if (strncmp(line, "model", 5) == 0) { const char *model_space = sanei_config_skip_whitespace(line + 5); DBG (10, "New Escl_Device MODEL [%s].", (model_space ? model_space : "VIDE")); if (escl_device != NULL && model_space != NULL) { @@ -453,7 +504,7 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line) escl_device->model_name = strdup(model_space); } } - if (strncmp(line, "type", 4) == 0) { + else if (strncmp(line, "type", 4) == 0) { const char *type_space = sanei_config_skip_whitespace(line + 4); DBG (10, "New Escl_Device TYPE [%s].", (type_space ? type_space : "VIDE")); if (escl_device != NULL && type_space != NULL) { @@ -461,6 +512,8 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line) escl_device->type = strdup(type_space); } } + escl_device->is = strdup("flatbed or ADF scanner"); + escl_device->uuid = NULL; status = escl_check_and_add_device(escl_device); if (status == SANE_STATUS_GOOD) escl_device = NULL; @@ -487,7 +540,8 @@ sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only) if (device_list == NULL) return (SANE_STATUS_INVAL); - status = sanei_configure_attach(ESCL_CONFIG_FILE, NULL, attach_one_config); + status = sanei_configure_attach(ESCL_CONFIG_FILE, NULL, + attach_one_config, NULL); if (status != SANE_STATUS_GOOD) return (status); escl_devices(&status); @@ -526,10 +580,156 @@ _source_size_max (SANE_String_Const * sources) return size; } +static int +_get_resolution(escl_sane_t *handler, int resol) +{ + int x = 1; + int n = handler->scanner->caps[handler->scanner->source].SupportedResolutions[0] + 1; + int old = -1; + for (; x < n; x++) { + DBG(10, "SEARCH RESOLUTION [ %d | %d]\n", resol, (int)handler->scanner->caps[handler->scanner->source].SupportedResolutions[x]); + if (resol == handler->scanner->caps[handler->scanner->source].SupportedResolutions[x]) + return resol; + else if (resol < handler->scanner->caps[handler->scanner->source].SupportedResolutions[x]) + { + if (old == -1) + return handler->scanner->caps[handler->scanner->source].SupportedResolutions[1]; + else + return old; + } + else + old = handler->scanner->caps[handler->scanner->source].SupportedResolutions[x]; + } + return old; +} + + +/** + * \fn static SANE_Status init_options(SANE_String_Const name, escl_sane_t *s) + * \brief Function thzt initializes all the needed options of the received scanner + * (the resolution / the color / the margins) thanks to the information received with + * the 'escl_capabilities' function, called just before. + * + * \return status (if everything is OK, status = SANE_STATUS_GOOD) + */ +static SANE_Status +init_options_small(SANE_String_Const name_source, escl_sane_t *s) +{ + int found = 0; + DBG (10, "escl init_options\n"); + + SANE_Status status = SANE_STATUS_GOOD; + if (!s->scanner) return SANE_STATUS_INVAL; + if (name_source) { + int source = s->scanner->source; + if (!strcmp(name_source, SANE_I18N ("ADF Duplex"))) + s->scanner->source = ADFDUPLEX; + else if (!strncmp(name_source, "A", 1) || + !strcmp(name_source, SANE_I18N ("ADF"))) + s->scanner->source = ADFSIMPLEX; + else + s->scanner->source = PLATEN; + if (source == s->scanner->source) return status; + s->scanner->caps[s->scanner->source].default_color = + strdup(s->scanner->caps[source].default_color); + s->scanner->caps[s->scanner->source].default_resolution = + _get_resolution(s, s->scanner->caps[source].default_resolution); + } + if (s->scanner->caps[s->scanner->source].ColorModes == NULL) { + if (s->scanner->caps[PLATEN].ColorModes) + s->scanner->source = PLATEN; + else if (s->scanner->caps[ADFSIMPLEX].ColorModes) + s->scanner->source = ADFSIMPLEX; + else if (s->scanner->caps[ADFDUPLEX].ColorModes) + s->scanner->source = ADFDUPLEX; + else + return SANE_STATUS_INVAL; + } + if (s->scanner->source == PLATEN) { + DBG (10, "SOURCE PLATEN.\n"); + } + else if (s->scanner->source == ADFDUPLEX) { + DBG (10, "SOURCE ADFDUPLEX.\n"); + } + else if (s->scanner->source == ADFSIMPLEX) { + DBG (10, "SOURCE ADFSIMPLEX.\n"); + } + s->x_range1.min = 0; + s->x_range1.max = + PIXEL_TO_MM((s->scanner->caps[s->scanner->source].MaxWidth - + s->scanner->caps[s->scanner->source].MinWidth), + 300.0); + s->x_range1.quant = 0; + s->x_range2.min = PIXEL_TO_MM(s->scanner->caps[s->scanner->source].MinWidth, 300.0); + s->x_range2.max = PIXEL_TO_MM(s->scanner->caps[s->scanner->source].MaxWidth, 300.0); + s->x_range2.quant = 0; + s->y_range1.min = 0; + s->y_range1.max = + PIXEL_TO_MM((s->scanner->caps[s->scanner->source].MaxHeight - + s->scanner->caps[s->scanner->source].MinHeight), + 300.0); + s->y_range1.quant = 0; + s->y_range2.min = PIXEL_TO_MM(s->scanner->caps[s->scanner->source].MinHeight, 300.0); + s->y_range2.max = PIXEL_TO_MM(s->scanner->caps[s->scanner->source].MaxHeight, 300.0); + s->y_range2.quant = 0; + + s->opt[OPT_MODE].constraint.string_list = s->scanner->caps[s->scanner->source].ColorModes; + if (s->val[OPT_MODE].s) + free(s->val[OPT_MODE].s); + s->val[OPT_MODE].s = NULL; + + if (s->scanner->caps[s->scanner->source].default_color) { + int x = 0; + if (!strcmp(s->scanner->caps[s->scanner->source].default_color, "Grayscale8")) + s->val[OPT_MODE].s = (char *)strdup(SANE_VALUE_SCAN_MODE_GRAY); + else if (!strcmp(s->scanner->caps[s->scanner->source].default_color, "BlackAndWhite1")) + s->val[OPT_MODE].s = (char *)strdup(SANE_VALUE_SCAN_MODE_LINEART); + else + s->val[OPT_MODE].s = (char *)strdup(SANE_VALUE_SCAN_MODE_COLOR); + for (x = 0; s->scanner->caps[s->scanner->source].ColorModes[x]; x++) { + if (s->scanner->caps[s->scanner->source].ColorModes[x] && + !strcasecmp(s->scanner->caps[s->scanner->source].ColorModes[x], s->val[OPT_MODE].s)) { + found = 1; + break; + } + } + } + if (!s->scanner->caps[s->scanner->source].default_color || found == 0) { + if (s->scanner->caps[s->scanner->source].default_color) + free(s->scanner->caps[s->scanner->source].default_color); + s->val[OPT_MODE].s = strdup(s->scanner->caps[s->scanner->source].ColorModes[0]); + if (!strcasecmp(s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY)) + s->scanner->caps[s->scanner->source].default_color = strdup("Grayscale8"); + else if (!strcasecmp(s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART)) + s->scanner->caps[s->scanner->source].default_color = strdup("BlackAndWhite1"); + else + s->scanner->caps[s->scanner->source].default_color = strdup("RGB24"); + } + if (!s->val[OPT_MODE].s) { + DBG (10, "Color Mode Default allocation failure.\n"); + return (SANE_STATUS_NO_MEM); + } + if (!s->scanner->caps[s->scanner->source].default_color) { + DBG (10, "Color Mode Default allocation failure.\n"); + return (SANE_STATUS_NO_MEM); + } + s->val[OPT_RESOLUTION].w = s->scanner->caps[s->scanner->source].default_resolution; + s->opt[OPT_TL_X].constraint.range = &s->x_range1; + s->opt[OPT_TL_Y].constraint.range = &s->y_range1; + s->opt[OPT_BR_X].constraint.range = &s->x_range2; + s->opt[OPT_BR_Y].constraint.range = &s->y_range2; + + if (s->val[OPT_SCAN_SOURCE].s) + free (s->val[OPT_SCAN_SOURCE].s); + s->val[OPT_SCAN_SOURCE].s = strdup (s->scanner->Sources[s->scanner->source]); + + return (SANE_STATUS_GOOD); +} + /** * \fn static SANE_Status init_options(SANE_String_Const name, escl_sane_t *s) * \brief Function thzt initializes all the needed options of the received scanner - * (the resolution / the color / the margins) thanks to the informations received with + * (the resolution / the color / the margins) thanks to the information received with * the 'escl_capabilities' function, called just before. * * \return status (if everything is OK, status = SANE_STATUS_GOOD) @@ -554,8 +754,25 @@ init_options(SANE_String_Const name_source, escl_sane_t *s) s->scanner->source = PLATEN; if (source == s->scanner->source) return status; } - else - s->scanner->source = PLATEN; + if (s->scanner->caps[s->scanner->source].ColorModes == NULL) { + if (s->scanner->caps[PLATEN].ColorModes) + s->scanner->source = PLATEN; + else if (s->scanner->caps[ADFSIMPLEX].ColorModes) + s->scanner->source = ADFSIMPLEX; + else if (s->scanner->caps[ADFDUPLEX].ColorModes) + s->scanner->source = ADFDUPLEX; + else + return SANE_STATUS_INVAL; + } + if (s->scanner->source == PLATEN) { + DBG (10, "SOURCE PLATEN.\n"); + } + else if (s->scanner->source == ADFDUPLEX) { + DBG (10, "SOURCE ADFDUPLEX.\n"); + } + else if (s->scanner->source == ADFSIMPLEX) { + DBG (10, "SOURCE ADFSIMPLEX.\n"); + } memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { @@ -590,6 +807,7 @@ init_options(SANE_String_Const name_source, escl_sane_t *s) s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; + s->opt[OPT_MODE_GROUP].size = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; @@ -599,17 +817,39 @@ init_options(SANE_String_Const name_source, escl_sane_t *s) s->opt[OPT_MODE].unit = SANE_UNIT_NONE; s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = s->scanner->caps[s->scanner->source].ColorModes; - s->val[OPT_MODE].s = (char *)strdup(s->scanner->caps[s->scanner->source].ColorModes[0]); + if (s->scanner->caps[s->scanner->source].default_color) { + if (!strcasecmp(s->scanner->caps[s->scanner->source].default_color, "Grayscale8")) + s->val[OPT_MODE].s = (char *)strdup(SANE_VALUE_SCAN_MODE_GRAY); + else if (!strcasecmp(s->scanner->caps[s->scanner->source].default_color, "BlackAndWhite1")) + s->val[OPT_MODE].s = (char *)strdup(SANE_VALUE_SCAN_MODE_LINEART); + else + s->val[OPT_MODE].s = (char *)strdup(SANE_VALUE_SCAN_MODE_COLOR); + } + else { + s->val[OPT_MODE].s = (char *)strdup(s->scanner->caps[s->scanner->source].ColorModes[0]); + if (!strcasecmp(s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY)) { + s->scanner->caps[s->scanner->source].default_color = strdup("Grayscale8"); + } + else if (!strcasecmp(s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART)) { + s->scanner->caps[s->scanner->source].default_color = + strdup("BlackAndWhite1"); + } + else { + s->scanner->caps[s->scanner->source].default_color = + strdup("RGB24"); + } + } if (!s->val[OPT_MODE].s) { DBG (10, "Color Mode Default allocation failure.\n"); return (SANE_STATUS_NO_MEM); } + DBG (10, "++ Color Mode Default allocation [%s].\n", s->scanner->caps[s->scanner->source].default_color); s->opt[OPT_MODE].size = max_string_size(s->scanner->caps[s->scanner->source].ColorModes); - s->scanner->caps[s->scanner->source].default_color = (char *)strdup(s->scanner->caps[s->scanner->source].ColorModes[0]); if (!s->scanner->caps[s->scanner->source].default_color) { DBG (10, "Color Mode Default allocation failure.\n"); return (SANE_STATUS_NO_MEM); } + DBG (10, "Color Mode Default allocation (%s).\n", s->scanner->caps[s->scanner->source].default_color); s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; @@ -638,6 +878,7 @@ init_options(SANE_String_Const name_source, escl_sane_t *s) s->opt[OPT_GEOMETRY_GROUP].desc = SANE_DESC_GEOMETRY; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; + s->opt[OPT_GEOMETRY_GROUP].size = 0; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; @@ -696,6 +937,113 @@ init_options(SANE_String_Const name_source, escl_sane_t *s) if (s->val[OPT_SCAN_SOURCE].s) free (s->val[OPT_SCAN_SOURCE].s); s->val[OPT_SCAN_SOURCE].s = strdup (s->scanner->Sources[s->scanner->source]); + + /* "Enhancement" group: */ + s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); + s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; /* not valid for a group */ + 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; + + + s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; + s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; + s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; + s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; + s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; + s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; + if (s->scanner->brightness) { + s->opt[OPT_BRIGHTNESS].constraint.range = &s->brightness_range; + s->val[OPT_BRIGHTNESS].w = s->scanner->brightness->normal; + s->brightness_range.quant=1; + s->brightness_range.min=s->scanner->brightness->min; + s->brightness_range.max=s->scanner->brightness->max; + } + else{ + SANE_Range range = { 0, 255, 0 }; + s->opt[OPT_BRIGHTNESS].constraint.range = ⦥ + s->val[OPT_BRIGHTNESS].w = 0; + s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; + } + s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; + s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; + s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; + s->opt[OPT_CONTRAST].type = SANE_TYPE_INT; + s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; + s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; + if (s->scanner->contrast) { + s->opt[OPT_CONTRAST].constraint.range = &s->contrast_range; + s->val[OPT_CONTRAST].w = s->scanner->contrast->normal; + s->contrast_range.quant=1; + s->contrast_range.min=s->scanner->contrast->min; + s->contrast_range.max=s->scanner->contrast->max; + } + else{ + SANE_Range range = { 0, 255, 0 }; + s->opt[OPT_CONTRAST].constraint.range = ⦥ + s->val[OPT_CONTRAST].w = 0; + s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; + } + s->opt[OPT_SHARPEN].name = SANE_NAME_SHARPEN; + s->opt[OPT_SHARPEN].title = SANE_TITLE_SHARPEN; + s->opt[OPT_SHARPEN].desc = SANE_DESC_SHARPEN; + s->opt[OPT_SHARPEN].type = SANE_TYPE_INT; + s->opt[OPT_SHARPEN].unit = SANE_UNIT_NONE; + s->opt[OPT_SHARPEN].constraint_type = SANE_CONSTRAINT_RANGE; + if (s->scanner->sharpen) { + s->opt[OPT_SHARPEN].constraint.range = &s->sharpen_range; + s->val[OPT_SHARPEN].w = s->scanner->sharpen->normal; + s->sharpen_range.quant=1; + s->sharpen_range.min=s->scanner->sharpen->min; + s->sharpen_range.max=s->scanner->sharpen->max; + } + else{ + SANE_Range range = { 0, 255, 0 }; + s->opt[OPT_SHARPEN].constraint.range = ⦥ + s->val[OPT_SHARPEN].w = 0; + s->opt[OPT_SHARPEN].cap |= SANE_CAP_INACTIVE; + } + /*threshold*/ + s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; + s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; + s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; + s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; + s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; + s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; + if (s->scanner->threshold) { + s->opt[OPT_THRESHOLD].constraint.range = &s->thresold_range; + s->val[OPT_THRESHOLD].w = s->scanner->threshold->normal; + s->thresold_range.quant=1; + s->thresold_range.min= s->scanner->threshold->min; + s->thresold_range.max=s->scanner->threshold->max; + } + else{ + SANE_Range range = { 0, 255, 0 }; + s->opt[OPT_THRESHOLD].constraint.range = ⦥ + s->val[OPT_THRESHOLD].w = 0; + s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; + } + if (!strcasecmp(s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART)) { + if (s->scanner->threshold) + s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; + if (s->scanner->brightness) + s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; + if (s->scanner->contrast) + s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; + if (s->scanner->sharpen) + s->opt[OPT_SHARPEN].cap |= SANE_CAP_INACTIVE; + } + else { + if (s->scanner->threshold) + s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; + if (s->scanner->brightness) + s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; + if (s->scanner->contrast) + s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; + if (s->scanner->sharpen) + s->opt[OPT_SHARPEN].cap &= ~SANE_CAP_INACTIVE; + } return (status); } @@ -745,6 +1093,50 @@ escl_parse_name(SANE_String_Const name, ESCL_Device *device) return SANE_STATUS_GOOD; } +static void +_get_hack(SANE_String_Const name, ESCL_Device *device) +{ + FILE *fp; + SANE_Char line[PATH_MAX]; + DBG (3, "_get_hack: start\n"); + if (device->model_name && + (strcasestr(device->model_name, "LaserJet FlowMFP M578") || + strcasestr(device->model_name, "LaserJet MFP M630"))) { + device->hack = curl_slist_append(NULL, "Host: localhost"); + DBG (3, "_get_hack: finish\n"); + return; + } + + /* open configuration file */ + fp = sanei_config_open (ESCL_CONFIG_FILE); + if (!fp) + { + DBG (2, "_get_hack: couldn't access %s\n", ESCL_CONFIG_FILE); + DBG (3, "_get_hack: exit\n"); + } + + /* loop reading the configuration file, all line beginning by "option " are + * parsed for value to store in configuration structure, other line are + * used are device to try to attach + */ + while (sanei_config_read (line, PATH_MAX, fp)) + { + if (strstr(line, name)) { + DBG (3, "_get_hack: idevice found\n"); + if (strstr(line, "hack=localhost")) { + DBG (3, "_get_hack: device found\n"); + device->hack = curl_slist_append(NULL, "Host: localhost"); + } + goto finish_hack; + } + } +finish_hack: + DBG (3, "_get_hack: finish\n"); + fclose(fp); +} + + + /** * \fn SANE_Status sane_open(SANE_String_Const name, SANE_Handle *h) * \brief Function that establishes a connection with the device named by 'name', @@ -786,6 +1178,8 @@ sane_open(SANE_String_Const name, SANE_Handle *h) escl_free_handler(handler); return (status); } + _get_hack(name, device); + status = init_options(NULL, handler); if (status != SANE_STATUS_GOOD) { escl_free_handler(handler); @@ -897,9 +1291,12 @@ sane_control_option(SANE_Handle h, SANE_Int n, SANE_Action a, void *v, SANE_Int case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: - case OPT_RESOLUTION: case OPT_PREVIEW: case OPT_GRAY_PREVIEW: + case OPT_RESOLUTION: + case OPT_BRIGHTNESS: + case OPT_CONTRAST: + case OPT_SHARPEN: *(SANE_Word *) v = handler->val[n].w; break; case OPT_SCAN_SOURCE: @@ -919,16 +1316,18 @@ sane_control_option(SANE_Handle h, SANE_Int n, SANE_Action a, void *v, SANE_Int case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: - case OPT_RESOLUTION: case OPT_PREVIEW: case OPT_GRAY_PREVIEW: + case OPT_BRIGHTNESS: + case OPT_CONTRAST: + case OPT_SHARPEN: handler->val[n].w = *(SANE_Word *) v; if (i) *i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; break; case OPT_SCAN_SOURCE: DBG(10, "SET OPT_SCAN_SOURCE(%s)\n", (SANE_String_Const)v); - init_options((SANE_String_Const)v, handler); + init_options_small((SANE_String_Const)v, handler); if (i) *i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; break; @@ -940,6 +1339,48 @@ sane_control_option(SANE_Handle h, SANE_Int n, SANE_Action a, void *v, SANE_Int DBG (10, "OPT_MODE allocation failure.\n"); return (SANE_STATUS_NO_MEM); } + DBG(10, "SET OPT_MODE(%s)\n", (SANE_String_Const)v); + + if (!strcasecmp(handler->val[n].s, SANE_VALUE_SCAN_MODE_GRAY)) { + handler->scanner->caps[handler->scanner->source].default_color = strdup("Grayscale8"); + DBG(10, "SET OPT_MODE(Grayscale8)\n"); + } + else if (!strcasecmp(handler->val[n].s, SANE_VALUE_SCAN_MODE_LINEART)) { + handler->scanner->caps[handler->scanner->source].default_color = + strdup("BlackAndWhite1"); + DBG(10, "SET OPT_MODE(BlackAndWhite1)\n"); + } + else { + handler->scanner->caps[handler->scanner->source].default_color = + strdup("RGB24"); + DBG(10, "SET OPT_MODE(RGB24)\n"); + } + DBG (10, "Color Mode allocation (%s).\n", handler->scanner->caps[handler->scanner->source].default_color); + if (i) + *i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; + if (handler->scanner->brightness) + handler->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; + if (handler->scanner->contrast) + handler->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; + if (handler->scanner->threshold) + handler->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; + if (handler->scanner->sharpen) + handler->opt[OPT_SHARPEN].cap |= SANE_CAP_INACTIVE; + if (!strcasecmp(handler->val[n].s, SANE_VALUE_SCAN_MODE_LINEART)) { + if (handler->scanner->threshold) + handler->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; + } + else { + if (handler->scanner->brightness) + handler->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; + if (handler->scanner->contrast) + handler->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; + if (handler->scanner->sharpen) + handler->opt[OPT_SHARPEN].cap &= ~SANE_CAP_INACTIVE; + } + break; + case OPT_RESOLUTION: + handler->val[n].w = _get_resolution(handler, (int)(*(SANE_Word *) v)); if (i) *i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; break; @@ -975,7 +1416,7 @@ _go_next_page(SANE_Status status, /** * \fn SANE_Status sane_start(SANE_Handle h) - * \brief Function that initiates aquisition of an image from the device represented by handle 'h'. + * \brief Function that initiates acquisition of an image from the device represented by handle 'h'. * This function calls the "escl_newjob" function and the "escl_scan" function. * * \return status (if everything is OK, status = SANE_STATUS_GOOD, otherwise, SANE_STATUS_NO_MEM/SANE_STATUS_INVAL) @@ -1005,11 +1446,13 @@ sane_start(SANE_Handle h) NULL); if (st != SANE_STATUS_GOOD) return st; - if(handler->scanner->caps[handler->scanner->source].default_color) - free(handler->scanner->caps[handler->scanner->source].default_color); if (handler->val[OPT_PREVIEW].w == SANE_TRUE) { - int i = 0, val = 9999;; + int i = 0, val = 9999; + + if(handler->scanner->caps[handler->scanner->source].default_color) + free(handler->scanner->caps[handler->scanner->source].default_color); + if (handler->val[OPT_GRAY_PREVIEW].w == SANE_TRUE || !strcasecmp(handler->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY)) handler->scanner->caps[handler->scanner->source].default_color = @@ -1032,15 +1475,18 @@ sane_start(SANE_Handle h) { handler->scanner->caps[handler->scanner->source].default_resolution = handler->val[OPT_RESOLUTION].w; - if (!strcasecmp(handler->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY)) - handler->scanner->caps[handler->scanner->source].default_color = strdup("Grayscale8"); - else if (!strcasecmp(handler->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART)) - handler->scanner->caps[handler->scanner->source].default_color = - strdup("BlackAndWhite1"); - else - handler->scanner->caps[handler->scanner->source].default_color = - strdup("RGB24"); + if (!handler->scanner->caps[handler->scanner->source].default_color) { + if (!strcasecmp(handler->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY)) + handler->scanner->caps[handler->scanner->source].default_color = strdup("Grayscale8"); + else if (!strcasecmp(handler->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART)) + handler->scanner->caps[handler->scanner->source].default_color = + strdup("BlackAndWhite1"); + else + handler->scanner->caps[handler->scanner->source].default_color = + strdup("RGB24"); + } } + DBG (10, "Before newjob Color Mode allocation (%s).\n", handler->scanner->caps[handler->scanner->source].default_color); handler->scanner->caps[handler->scanner->source].height = MM_TO_PIXEL(handler->val[OPT_BR_Y].w, 300.0); handler->scanner->caps[handler->scanner->source].width = @@ -1066,6 +1512,67 @@ sane_start(SANE_Handle h) DBG (10, "Default Color allocation failure.\n"); return (SANE_STATUS_NO_MEM); } + + if (handler->scanner->threshold) { + DBG(10, "Have Thresold\n"); + if (IS_ACTIVE(OPT_THRESHOLD)) { + DBG(10, "Use Thresold [%d]\n", handler->val[OPT_THRESHOLD].w); + handler->scanner->val_threshold = handler->val[OPT_THRESHOLD].w; + handler->scanner->use_threshold = 1; + } + else { + DBG(10, "Not use Thresold\n"); + handler->scanner->use_threshold = 0; + } + } + else + DBG(10, "Don't have Thresold\n"); + + if (handler->scanner->sharpen) { + DBG(10, "Have Sharpen\n"); + if (IS_ACTIVE(OPT_SHARPEN)) { + DBG(10, "Use Sharpen [%d]\n", handler->val[OPT_SHARPEN].w); + handler->scanner->val_sharpen = handler->val[OPT_SHARPEN].w; + handler->scanner->use_sharpen = 1; + } + else { + DBG(10, "Not use Sharpen\n"); + handler->scanner->use_sharpen = 0; + } + } + else + DBG(10, "Don't have Sharpen\n"); + + if (handler->scanner->contrast) { + DBG(10, "Have Contrast\n"); + if (IS_ACTIVE(OPT_CONTRAST)) { + DBG(10, "Use Contrast [%d]\n", handler->val[OPT_CONTRAST].w); + handler->scanner->val_contrast = handler->val[OPT_CONTRAST].w; + handler->scanner->use_contrast = 1; + } + else { + DBG(10, "Not use Contrast\n"); + handler->scanner->use_contrast = 0; + } + } + else + DBG(10, "Don't have Contrast\n"); + + if (handler->scanner->brightness) { + DBG(10, "Have Brightness\n"); + if (IS_ACTIVE(OPT_BRIGHTNESS)) { + DBG(10, "Use Brightness [%d]\n", handler->val[OPT_BRIGHTNESS].w); + handler->scanner->val_brightness = handler->val[OPT_BRIGHTNESS].w; + handler->scanner->use_brightness = 1; + } + else { + DBG(10, "Not use Brightness\n"); + handler->scanner->use_brightness = 0; + } + } + else + DBG(10, "Don't have Brightness\n"); + handler->result = escl_newjob(handler->scanner, handler->device, &status); if (status != SANE_STATUS_GOOD) return (status); @@ -1104,7 +1611,7 @@ sane_start(SANE_Handle h) status = get_PDF_data(handler->scanner, &w, &he, &bps); } else { - DBG(10, "Unknow image format\n"); + DBG(10, "Unknown image format\n"); return SANE_STATUS_INVAL; } @@ -1257,6 +1764,12 @@ escl_curl_url(CURL *handle, const ESCL_Device *device, SANE_String_Const path) DBG( 1, "escl_curl_url: URL: %s\n", url ); curl_easy_setopt(handle, CURLOPT_URL, url); free(url); + DBG( 1, "Before use hack\n"); + if (device->hack) { + DBG( 1, "Use hack\n"); + curl_easy_setopt(handle, CURLOPT_HTTPHEADER, device->hack); + } + DBG( 1, "After use hack\n"); if (device->https) { DBG( 1, "Ignoring safety certificates, use https\n"); curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0L); -- cgit v1.2.3